2012-12-05 53 views
1

有人可以从REPL解释下面的输出吗?Scala Stream By One

我正在定义2个(无限)流,除非之前有,否则其定义相同。一个定义中的(句点)和另一个中的__(空格)。

我可以看到,这会导致地图绑定不同,但会发生什么情况输出从第二个定义?

谢谢。

scala> lazy val infinite: Stream[Int] = 1 #:: infinite.map(_+1) 
infinite: Stream[Int] = <lazy> 

scala> val l = infinite.take(10).toList.mkString(",") 
l: String = 1,2,3,4,5,6,7,8,9,10 

scala> lazy val infinite2: Stream[Int] = 1 #:: infinite2 map(_+1) 
infinite2: Stream[Int] = <lazy> 

scala> val l2 = infinite2.take(10).toList.mkString(",") 
l2: String = 2,3,4,5,6,7,8,9,10,11 

回答

11

这是关于method associativity。这:

1 #:: infinite.map(_+1) 

是相当简单的,而这一点:

1 #:: infinite2 map(_+1) 

是由编译器解释为:

(1 #:: infinite2) map(_+1) 

1 #:: infinite2是你所需的视频流,但是你回到它之前,你申请懒惰转换为每个项目添加一个。这就解释了为什么1从未出现过 - 在转换后它变成了2

详情请参阅:Operator precedence in Scala。由于#不是特殊字符,因此它与map同等对待,因此方法从左到右进行评估。

+0

酷!得到它了。谢谢! –

+0

@BillBarrington:没问题。如果您的问题得到解决,请接受/ upvote或其他答案。 –

1

在infinite2情况下,你已经表达等同于以下内容:

lazy val infinite2: Stream[Int] = (1 #:: infinite2) map(_ + 1) 

由于流从1开始,地图将增加1到第一个元素。