Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scalas (a,b).zipped (or Tuple2.zipped) notion using streams/infinite lists

here is what I thought would be a correct and useful definition of fibonacci nums in scala:

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

However, I get the following error:

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...

I guess zipped doesn't work correctly with streams? Any suggestions on how to make this work, or why this doesnt( shouldn't? ) work?

like image 362
Felix Avatar asked Mar 11 '11 17:03

Felix


1 Answers

The following works correctly

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

The problem with Tuple2.zipped is that it assumes it can run foreach on sequences it's zipping. This is probably by design, as doing things the way Stream.zip implements it would probably give you bad performance for any finite-length Seq that isn't a List or Stream. (Because most data structures don't support an efficient implementation of tail.)


Stream.zip is essentially implemented as follows (though it does some stuff to make the types more general).

class Stream[A]{
  def zip(other:Stream[B]) =
    (this.head, other.head) #:: (this.tail zip other.tail)
}
like image 107
Ken Bloom Avatar answered Oct 15 '22 07:10

Ken Bloom