In my comment, I pointed out that your implementations cannot be optimized using the tail, because in the case where yy % 2 == 0 , there is a recursive call that is not in the tail position. Thus, for large input, this can overflow the stack.
A common solution is your function trampoline, replacing recursive calls with data that can be mapped to "post-processing", such as sqr . The result is then evaluated by the interpreter, which executes the return values, storing them on the heap, and not on the stack.
The Scalaz library provides data type and interpreter implementations.
import scalaz.Free.Trampoline, scalaz.Trampoline._ def sqr(z: Double): Double = z * z def power(x: Double, y: Int): Double = { def loop(xx: Double, yy: Int): Trampoline[Double] = if (yy == 0) done(xx) else if (yy % 2 == 0) suspend(loop(xx, yy / 2)) map sqr else suspend(loop(xx * x, yy - 1)) loop(1.0, y).run }
However, there is significant success. In this particular case, I would use the Igno solution to avoid having to call sqr at all. But the technique described above can be useful when you cannot do such an optimization for your algorithm.
source share