2011-03-11 36 views
6

这里是我认为将是斐波那契NUMS的Scala中的一个正确和有用的定义:Scalas(A,B).zipped(或Tuple2.zipped)概念使用流/无限列表

lazy val fibs:Stream[Int] = 0 #:: 1 #:: (fibs,fibs.tail).zipped.map(_+_) 

然而,我收到以下错误:

fibs take 10 foreach println 
0 
1 
java.lang.StackOverflowError 
    at scala.collection.mutable.LazyBuilder.(LazyBuilder.scala:25) 
    at scala.collection.immutable.Stream$StreamBuilder.(Stream.scala:492) 
    at scala.collection.immutable.Stream$.newBuilder(Stream.scala:483) 
    at... 

我猜压缩不能正确使用流?关于如何做这项工作的任何建议,或为什么这不(不应该?)工作?

+0

我只是要问这个_exact_问题。很想知道有人在我面前来到这里。 +1 – KChaloux

回答

8

下工作正常

val fibs:Stream[Int] = 0 #:: 1 #:: (fibs zip fibs.tail).map{ case (a,b) => a+b } 

Tuple2.zipped的问题在于,它假定它可以在它的压缩和解序列运行foreach。这可能是通过设计,因为按照Stream.zip实现它的方式进行处理可能会给您带来不良影响,因为任何有限长度的Seq都不是ListStream。 (因为数据结构不支持高效实现tail


Stream.zip基本上实现如下(尽管它的一些东西,使更多的类型一般)。

class Stream[A]{ 
    def zip(other:Stream[B]) = 
    (this.head, other.head) #:: (this.tail zip other.tail) 
} 
+0

虽然您的问题中的“懒惰”限定符是不必要的,但我向你保证,在我的答案中删除它并不是做这项工作的原因。 –

+0

好吧,你已经展示的是非常好的:)我想这只是表明我们需要多少“zipWith”,它需要一个2-arity函数作为参数,比如在haskell中。我真的不明白为什么它不在Scala中? – Felix

+1

@Felix:我不明白'zipWith'会有什么帮助。元组上的'zipWith'仍然会作为foreach实现,当第一个列表是无限流时会溢出。 –

3

有一个在Scala的Trac的数据库,在这个一票:http://lampsvn.epfl.ch/trac/scala/ticket/2634

票关闭作为wontfix,但注意阿德里安的“或者,我们失去了一些东西?”在评论中 - 也许这将会有一天会重新审视。

相关问题