This is because scalac does not optimize the loop
inside getReaderLines
for tail calls. loop
is tail recursive, but I think the syntax of case
anonymous functions gets in the way.
Edit : this is actually not even tail recursion (a wrapper in the IO monad) causes at least one more call after a recursive call. When I tested my testing yesterday, I used the same code, but I dropped the IO monad, and then it was possible to make a Iteratee reverse tail. The text below suggests that IO monad ...
I accidentally discovered this yesterday while experimenting with iterations. I think changing the loop
signature to this will help (so for now you have to override getFilesLines
and getReaderLines
:
@annotations.tailrec def loop(it: IterV[String, A]): IO[IterV[String, A]] = it match { // ... }
We should probably report this to the scalaz community (and an expansion ticket for scala may be open).
This shows what is happening (the code is vaguely similar to getReaderLines.loop
):
@annotation.tailrec def f(i: Int): Int = i match { case 0 => 0 case x => f(x - 1) } // f: (i: Int)Int @annotation.tailrec def g: Int => Int = { case 0 => 0 case x => g(x - 1) } /* error: could not optimize @tailrec annotated method g: it contains a recursive call not in tail position def g: Int => Int = { ^ */
source share