2012-03-24 64 views
0

我有一个深深的“嵌套”的理解,简化到3层以下:x,y和z。我希望做只有X A Stream将使y和z计算懒惰太:嵌套懒理解

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个打印证明。我只想计算前两个,因为这些都是我从流中提取的。我可以通过在第二个List等上调用toStream来解决此问题。有没有更好的方法比在理解的每个级别上调用?

回答

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的头被评估。

你是对的,如果你只希望逐个处理每个结果元素,那么所有的生成器都必须是流。如下例所示,您可以通过让Streams开始,呼叫toStream

streamStream[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是'单位'。现在有3个打印前面,即使我只采取流的前2个元素和'doSomething'。我如何使第三次打印(“计算”)不会发生? – Bluu 2012-03-24 06:32:07

+0

@Bluu这三个计算是针对'y'的每个元素,应该从“1”数字中清楚。就像我说的,头部总是被评估。尝试'流4取foreach println',你会看到,第二批只计算前3后采取 – 2012-03-24 06:39:17

+0

我现在看到。谢谢。为了严格评估head_的头部,这就是为什么我需要调用List(“foo”,“bar”,“baz”)。toStream'。你知道有什么方法吗? – Bluu 2012-03-24 18:08:58