Any recursive function can be converted to use a heap, not a stack, to track context. This process is called trampolining .
Here's how to do it with Scalaz.
object TrampolineUsage extends App { import scalaz._, Scalaz._, Free._ def quickSort[T: Order](xs: List[T]): Trampoline[List[T]] = { assert(Thread.currentThread().getStackTrace.count(_.getMethodName == "quickSort") == 1) xs match { case Nil => return_ { Nil } case x :: tail => val (left, right) = tail.partition(_ < x) suspend { for { ls <- quickSort(left) rs <- quickSort(right) } yield ls ::: (x :: rs) } } } val xs = List.fill(32)(util.Random.nextInt()) val sorted = quickSort(xs).run println(sorted) val (steps, sorted1) = quickSort(xs).foldRun(0)((i, f) => (i + 1, f())) println("sort took %d steps".format(steps)) }
Of course, you need either a very large structure or a really small stack in order to have a practical problem with the algorithm without tail-recursive separation and subjugation, since you can handle 2 ^ N elements with a stack depth of N.
http://blog.richdougherty.com/2009/04/tail-calls-tailrec-and-trampolines.html
UPDATE
scalaz.Trampoline is a special case of a (much) more general structure, Free . It is defined as type Trampoline[+A] = Free[Function0, A] . In fact, you can write quickSort more general, so it is parameterized by the type constructor used in Free . This example shows how this is done, and how you can use the same code for binding using a stack, heap, or at the same time.
https://github.com/scalaz/scalaz/blob/scalaz-seven/example/src/main/scala/scalaz/example/TrampolineUsage.scala
source share