2010-06-02 10 views
7

Sto definendo un flusso in termini di se stesso (una definizione ricorsiva). Quando si tenta di accedere al secondo elemento del flusso, viene generato StackOverflowError. Il codice dalla console di scala:Stream ricorsivo genera StackOverflowError

scala> val s1 = Stream.iterate(1)(identity _) 
s1: scala.collection.immutable.Stream[Int] = Stream(1, ?) 

scala> lazy val s2 : Stream[Int]= Stream.cons(1, (s2, s1).zipped.map { _ + _ }) 
s2: Stream[Int] = <lazy> 

scala> s1 take 5 print 
1, 1, 1, 1, 1, empty 
scala> s2(0) 
res4: Int = 1 

scala> s2(1) 
java.lang.StackOverflowError 
     at $anonfun$s2$1$$anonfun$apply$1.apply(<console>:9) 
     at $anonfun$s2$1$$anonfun$apply$1.apply(<console>:9) 
     at scala.Tuple2$Zipped$$anonfun$map$1.apply(Tuple2.scala:62) 
     at scala.collection.immutable.Stream.foreach(Stream.scala:255) 
     at scala.Tuple2$Zipped.map(Tuple2.scala:60) 
     at $anonfun$s2$1.apply(<console>:9) 
     at $anonfun$s2$1.apply(<console>:9) 
     at scala.collection.immutable.Stream$Cons.tail(Stream.scala:556) 
     at scala.collection.immutable.Stream$Cons.tail(Stream.scala:550) 
     at scala.collection.immutable.Stream.foreach(Stream.scala:256) 
     at scala.Tuple2$Zipped.map(Tuple2.scala:60) 
     at $anonfun$s2$1.apply(<console>:9) 
     at $anonfun$s2$1.apply(<console>:9) 
     at scala.collection.immutable.Stream$Cons.tail(Stream.scala:556) 
     at scala.collection.immutable.Str... 

Non riesco a capire il motivo dell'overflow dello stack. Poiché gli stream sono intrinsecamente pigri, la mappatura ricorsiva dovrebbe funzionare.

Cosa c'è di sbagliato in questo scenario?

Sto usando la versione 2.8.0.RC2 di Scala.

risposta

8

Il problema è che zipped non è pigro - in realtà tenta di valutare quella mappa proprio lì. Puoi fare quello che vuoi con zip.

scala> val s1 = Stream.iterate(1)(identity _) 
s1: scala.collection.immutable.Stream[Int] = Stream(1, ?) 

scala> lazy val s2: Stream[Int] = Stream.cons(1, (s2 zip s1).map {s=>s._1+s._2}) 
s2: Stream[Int] = <lazy> 

scala> s2 take 5 print 
1, 2, 3, 4, 5, empty 
+1

è http://lampsvn.epfl.ch/trac/scala/ticket/2634 –