2012-03-24 16 views
0

Ich habe eine tief "geschachtelt" für das Verständnis, vereinfacht auf 3 Ebenen darunter: x, y und z. Ich hatte gehofft, machen nur x eine Stream wäre zu der y- und z-Berechnungen faul:Verschachtelt faul zum Verständnis

val stream = for { 
    x <- List(1, 2, 3).toStream 
    y <- List("foo", "bar", "baz") 
    z = { 
    println("Processed " + x + y) 
    x + y 
    } 
} yield z 

stream take (2) foreach (doSomething) 

Aber diese berechnet alle drei Elemente, wie sie durch die 3 Drucke belegt. Ich möchte nur die ersten 2 berechnen, da das alles ist, was ich aus dem Stream nehme. Ich kann umgehen, indem ich toStream auf dem zweiten List und so weiter rufe. Gibt es einen besseren Weg als das auf jeder Ebene des Verständnisses zu nennen?

Antwort

3

Was druckt es ist:

Processed 1foo 
Processed 1bar 
Processed 1baz 
stream: scala.collection.immutable.Stream[String] = Stream(1foo, ?) 

scala> stream take (2) foreach (println) 
1foo 
1bar 

Der Kopf eines Stream wird immer streng ausgewertet, weshalb Sie sehen Processed 1foo etc und nicht Processed 2foo usw. gedruckt wird, wenn Sie die Stream-schaffen, genauer , wenn der Kopf von stream ausgewertet wird.

Sie haben Recht, wenn Sie nur jedes einzelne Element einzeln bearbeiten wollen, müssen alle Generatoren Streams sein. Sie könnten umhergehen und toStream anrufen, indem Sie sie mit Streams starten, wie im Beispiel unten.

stream ist ein Stream[String] und sein Kopf muss ausgewertet werden. Wenn Sie nicht mit Spannung Wert berechnen wollen, können Sie entweder prepend einen Dummy-Wert, oder besser, um Ihren Wert streamlazy:

lazy val stream = for { 
    x <- Stream(1, 2, 3) 
    y <- Stream("foo", "bar", "baz") 
    z = { println("Processed " + x + y); x + y } 
} yield z 

Dies gilt nicht tun, um jede „Verarbeitung“, bis Sie nehmen jeweils Wert:

scala> stream take 2 foreach println 
Processed 1foo 
1foo 
Processed 1bar 
1bar 
+0

Clarified meine Frage. Ich hatte nicht vor, z "Einheit" zu sein. Jetzt gibt es 3 Drucke im Voraus, obwohl ich nur die ersten 2 Elemente des Streams nehme und mit ihnen "etwas mache". Wie mache ich den 3. Druck ("Berechnung") nicht? – Bluu

+0

@Bluu die drei Berechnungen sind für jedes Element von "y", wie aus der "1" Nummer klar sein sollte. Wie gesagt, der Kopf wird immer ausgewertet. Versuchen Sie 'stream take 4 foreach println' und Sie werden sehen, dass die zweite Charge nur berechnet wird, nachdem die ersten 3 genommen wurden –

+0

Ich sehe jetzt. Vielen Dank. Und nur den Kopf des Kopfs streng zu bewerten, deshalb muss ich 'List (" foo "," bar "," baz ") nennen. ToStream'. Kennen Sie das? – Bluu