2010-09-20 16 views
23

Ich habe gefunden, dass Scala immer eine "natürliche Erklärung" zu irgendetwas hat. Immer etwas wie "ohh, aber das ist nur eine Funktion, die an diesem und jenem Objekt mit diesem und diesem Parameter aufgerufen wird". In gewissem Sinne ist nichts wirklich Compiler-Magie, wie wir es aus anderen Sprachen kennen.Scala "<-" für das Verständnis

Meine Frage ist auf der <- Operator wie in den folgenden Code verwendet:

for(i <- 0 to 10) println(i) 

In diesem Beispiel habe ich es so etwas wie neu geschrieben sehen:

0.to(10).foreach((i:Int)=>println(i)) 

aber das erklärt nicht, wie die i in die anon getragen wurde ymous Funktion innerhalb der Foreach-Funktion. An dem Punkt, wo Sie schreiben ich ist es kein Objekt, und noch nicht eine deklarierte Variable. Was ist es und wie wird es in das Innere von foreach übertragen?

Meine Vermutung ist, dass ich endlich etwas gefunden, die in der Tat Compiler ist Magie

Vielen Dank für Ihre Zeit.

Um zu klären, meine Frage ist: Wie funktioniert die < - Operator Arbeit in der ersten Zeile des Codes, da ich an dem nicht ein Objekt ist, kann es als eine Funktion aufgerufen werden.

Antwort

18

<- eine Sprache ist, -defined Schlüsselwort-Symbol, wie => aber im deutlichen Gegensatz zu -> (die ein definiertes Symbol ist). Da es Teil der grundlegenden Scala-Grammatik ist, kann es verwendet werden, um Bindungen zu erstellen (für die i in Ihrem Beispiel), was nicht durch benutzerdefinierte Konstrukte möglich ist.

+0

Dies scheint die Antwort zu sein. Ich würde vorschlagen, dass Sie dies dokumentieren, wenn es möglich ist, es ist jetzt irgendwie aus heiterem Himmel. – Felix

+4

@Felix: Es ist in der Spezifikation dokumentiert. Und so ziemlich jedes Scala-Buch, das auf dem Markt erhältlich ist, deckt es ab. – missingfaktor

+0

oh yeah, ich habe noch kein Buch bekommen. Warten auf das definitive 2.8 Buch – Felix

6

In diesem Fall ist es wirklich ein bisschen Compiler Magie. Die Übersetzung von For-Comprehension zu Filter/Map/Flatmap-Form ist ein besonderes Stück Entzuckerung, ähnlich der Konvertierung der speziellen Formen von Update- und Apply-Methoden.

57

Dave Antwort auf vermehren, ist hier ein Übersetzungsschema für ‚for-Comprehensions‘ von der Spezifikation Scala Sprache:

Ein Verständnis for (enums) yield e wertet e Ausdruck für jede von den Aufzählungen Aufzählungen erzeugt Bindung. Eine Enumeratorsequenz beginnt immer mit einem Generator; Danach können weitere Generatoren, Wertdefinitionen oder Wächter folgen.

Ein Generator p <- e erzeugt Bindungen von einem Ausdruck e, der in gewisser Weise gegen Muster p abgestimmt ist. Eine Wertdefinition val p = e bindet den Wertnamen (oder mehrere Namen in einem Muster p) an das Ergebnis der Auswertung des Ausdrucks e. Ein Schutz if e enthält einen booleschen Ausdruck, der aufgezählte Bindungen einschränkt. map, filter, flatMap und foreach:

Die genaue Bedeutung von Generatoren und Wachen durch Übersetzung Anrufungen von vier Methoden definiert. Diese Methoden können für verschiedene Trägertypen auf unterschiedliche Weise implementiert werden.

Das Übersetzungsschema ist wie folgt. In einem ersten Schritt wird jeder Generator p <- e, wobei p nicht unwiderlegbar ist (§8.1) für die Art der e ersetzt wird durch

p <- e.filter { case p => true; case _ => false } 

Dann werden die folgenden Regeln angewendet wiederholt, bis alle Comprehensions eliminiert.

  • A für Verständnis for (p <- e) yield e0 wird e.map { case p => e0 } übersetzt.

  • Ein für das Verständnis for (p <- e) e0 ist in e.foreach { case p => e0 } übersetzt.

  • Ein für das Verständnis for (p <- e; p0 <- e0 . . .) yield e00, wo. . . ist eine (möglicherweise leere) Folge von Generatoren oder Schutzeinrichtungen, die übersetzt wird zu:
    e.flatMap { case p => for (p0 <- e0 . . .) yield e00 }.

  • Ein für das Verständnis for (p <- e; p0 <- e0 . . .) e00 wo. . . ist eine (möglicherweise leere) Folge von Generatoren oder Schutzvorrichtungen, übersetzt in:
    e.foreach { case p => for (p0 <- e0 . . .) e00 }.

  • Ein Generator p <- e von einer Wache gefolgt if g zu einem einzigen Generator übersetzt:
    p <- e.filter((x1, . . . , xn) => g)
    wo x1. . . xn sind die freien Variablen von p.

  • Ein Generator p <- e durch einen Wert Definition gefolgt val p0 = e0 wird den folgenden Generator von Wertepaaren übersetzt, wo x und x0 frische Namen sind:

    val (p, p0) <- 
        for([email protected] <- e) yield { val [email protected] = e0; (x, x0) } 
    
+1

Okay, ich verstehe nicht alles nach dem ersten Lesen, aber es ist interessant :-) Wo hast du das bekommen? – Felix

+0

@Felix: Wie ich oben auf der Antwort sagte, ist es aus der Sprachspezifikation (kann von www.scala-lang.org heruntergeladen werden) – missingfaktor

Verwandte Themen