[scala] Why does calling sumr on a stream with 50 tuples not complete

While investigating a bug today, I noticed that calling sumr on a stream with 50 (Int, Int) tuples never completes, but it does on a smaller stream. Calling .toList on the larger stream first completes as well.

Is this the intended behavior when calling sumr on a large stream? Does it not evaluate the stream to completion, or is something else causing this?

scala> val strSmall = Stream((1,1),(2,4),(3,9),(4,16),(5,25)) strSmall: scala.collection.immutable.Stream[(Int, Int)] = Stream((1,1), ?)  scala> val strBig = Stream((1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (0,1), (1,0), (1,0), (1,0), (1,0), (0,1), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (1,0), (0,1), (1,0), (1,0), (1,0), (1,0), (1,0)) strBig: scala.collection.immutable.Stream[(Int, Int)] = Stream((1,0), ?)  scala> strSmall.sumr res3: (Int, Int) = (15,55)  scala> strBig.toList.sumr res4: (Int, Int) = (47,3)  scala> strBig.sumr <!-- never completes --> 

This question is related to scala stream scalaz

The answer is


sumr is implemented in terms of foldRight:

 final def sumr(implicit A: Monoid[A]): A = F.foldRight(self, A.zero)(A.append) 

foldRight is not always tail recursive, so you can overflow the stack if the collection is too long. See Why foldRight and reduceRight are NOT tail recursive? for some more discussion of when this is or isn't true.