2012-12-30 18 views
19

Ich bin neugierig - was ist der Sinn der generischen Art U in der Erklärung Traversableforeach Methode?Was ist der generische Typ in foreach?

def foreach[U](f: A => U): Unit 

Seit Rückgabetyp Function1 covariant ist, warum kann das nicht einfach sein:

def foreach(f: A => Any): Unit 

?

+0

Ich habe keine Zeit, um ein Beispiel zu finden, aber ich vermute stark, dass es der Typinfinferator 'foreach' ignorieren soll, wenn es darum geht, den Rückgabetyp einer Funktion zu bestimmen. Aber ich kenne keinen Fall von oben, wo es wichtig wäre (d. H. Dass "Any" nicht zu demselben Schluss führen würde). –

Antwort

9

Nicht in dem Martin Odersky Ich kann nur raten :-) Wenn ich das Scaladoc von foreach betrachte, sehe ich folgendes:

/** Applies a function `f` to all elements of this $coll. 
    * 
    * @param f the function that is applied for its side-effect to every element. 
    *    The result of function `f` is discarded. 
    *    
    * @tparam U the type parameter describing the result of function `f`. 
    *    This result will always be ignored. Typically `U` is `Unit`, 
    *    but this is not necessary. 
    * 
    * @usecase def foreach(f: A => Unit): Unit 
    */ 

So ist der Rückgabetyp von f egal und sein Ergebnis wird immer verworfen. Dies bedeutet für mich, dass die Verwendung eines generischen Typparameters hier, um den Rückgabetyp zu markieren, nur eine subtile Dokumentation ist und sagt: "Der Rückgabetyp kann alles sein, wirklich alles, was du magst". Während ein Rückgabetyp von Any (einigen) Lesern eine gewisse Einschränkung der hier anwendbaren Funktionstypen nahelegen kann.

Ein anderer Aspekt ist, dass Scala sehr bewusst entworfen wurde, um von Grund auf generisch zu sein. Also - für mich - die Verwendung eines generischen Typparameters steht hier im Einklang mit der allgemeinen Philosophie der Sprache, während die Verwendung von Any - obwohl technisch verwendbar - ein definitiv nicht-generischer Ansatz wäre, der mit dem Rest der Sprache im Widerspruch stehen würde.

-5

Vielleicht, damit Sie von einer Traversable erben, und verwenden Sie den Rückgabewert U von f: A => U?

trait TraversableWithHandler[+A, E <: Option[Throwable]] extends Traversable[A] { 
    override def foreach[U](f: A => U): Unit 
    def handleError(t: E) 
} 

Zum Beispiel in jQuery, Rückkehr von false von innen zu foreachbreak äquivalent ist, anders Wert ist ein continue.

Use Case

breakable { 
    List(1,2,3).foreach(_ match { 
    case 1 => println("ok") 
    case 2 => 
     println("Sort of, soft interrupt?") 
     return false 
    case 3 => break 
    }) 
} 

Da der nächste Code (parallel), nie bricht (stackless throwable Lösung in diesem Fall nicht ideal zu sein scheint?):

import scala.util.control.Breaks._ 

breakable { 
    (0 to 100).toList.par.foreach(_ match { 
    case n if (n <= 50) => 
     println("#" * 100) 
     try { break } catch { 
     case t: Throwable => println("" + t); break 
     } 
    case n if (n > 50) => 
     println("" + n) 
    case _ => "ok" 
    }) 
} 
+0

-1: Da stackless Ausnahmen ohnehin für den Kontrollfluss in solchen Situationen verwendet werden und ein formaler Rückgabewert in einem solchen Fall nutzlos ist, ist dies _highly_ unwahrscheinlich. Außerdem zeigen Sie keine Anwendungsfälle. Ich habe keine Ahnung, wie ich die obige Signatur verwenden soll. –

+0

Dies würde im Gegensatz zu der Scaladoc stehen, die sagt: "Das Ergebnis der Funktion' f' wird verworfen. " –

+5

Diese Antwort ist nicht nur falsch, es ist möglicherweise sehr verwirrend. Sie haben den Typparameter gerade so umbenannt, dass er 'scala.Boolean' schattiert - Sie haben die Methode, die in' Traversable' deklariert wurde, definitiv nicht eingeschränkt. –

Verwandte Themen