2012-03-24 6 views
0

У меня есть глубокое «вложенное» для понимания, упрощенное до трех уровней ниже: x, y и z. Я надеялся, что делает только х в Stream бы у и г вычисления ленивых тоже:Вложенное ленивое для понимания

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) 

Но это вычисляет все 3 элемента, о чем свидетельствует 3 гравюр. Я бы хотел только вычислить первые 2, так как это все, что я беру из потока. Я могу обойти это, позвонив toStream на второй List и так далее. Есть ли лучший способ, чем называть это на каждом уровне понимания?

ответ

3

Что он печатает это:

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

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

Голова Stream всегда строго оценивали, поэтому вы видите Processed 1foo и т.д., а не Processed 2foo и т.д. Это печатается, когда вы создаете поток, точнее , когда оценивается глава stream.

Вы правы, что если вы хотите обрабатывать каждый результирующий элемент один за другим, тогда все генераторы должны быть потоками. Вы можете обойти вызов toStream, сделав для них Streams, как в примере ниже.

stream - Stream[String], и его голова должна быть оценена. Если вы не хотите, чтобы вычислить значение жадностью, вы можете либо предварять фиктивное значение, или лучше, сделать свою ценность streamlazy:

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

Это не делает каких-либо «обработки», пока вы не будете принимать каждый значение:

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

Уточненный вопрос. Я не собирался z быть «Unit». Теперь есть 3 печати вверх, хотя я беру только первые 2 элемента потока и 'doSomething' с ними. Как сделать 3-й отпечаток («расчет») не произойдет? – Bluu

+0

@Bluu три вычисления для каждого элемента 'y', как следует из числа« 1 ». Как я уже сказал, голова всегда оценивается. Попробуйте 'stream take 4 foreach println', и вы увидите, что вторая партия вычисляется только после того, как первые 3 взяты –

+0

Теперь я вижу. Благодарю. И только для того, чтобы строго оценивать голову головы, вот почему мне нужно вызвать «Список» («foo», «bar», «baz»). ToStream'. Знаете ли вы об этом? – Bluu

Смежные вопросы