- def fibonacci(n: Int): Int =
- @tailrec
- def fibHelper(n: Int, a: Int, b: Int): Int = n match
- case 0 => a
- case _ => fibHelper(n - 1, b, a + b)
- end fibHelper
- fibHelper(n, 0, 1)
- end fibonacci
tailrec annotation: compiler error if not tail-recursiveTail-recursive accumulator
- def sum (xs:List[Int], z:Int = 0) : Int =
- xs match
- case Nil => z
- case x::rest => sum (rest, z+x)
- end sum
- var s = sum(List(1,2,3))
Tail-recursive continuation passing
- def sum (xs:List[Int], c:Int=>Unit) : Unit =
- xs match
- case Nil => c(0)
- case x::rest => sum (rest, y=>c(x+y))
- end sum
- var s = -1
- sum(List(1,2,3), s=_)
Tail-recursive
- def factorial (n:Int) : Int =
- @tailrec
- def loop (m:Int, result:Int) : Int =
- if m > 1 then loop(m-1, m*result)
- else result
- loop(n,1)
Recursive (mutable)
- def factorial (n:Int) : Int =
- var result = 1
- def loop (m:Int) : Unit =
- if m > 1 then
- result = result*m
- loop(m-1)
- loop(n)
- result
- def factorial (n:Int) : Int =
- var result = 1
- var m = n
- def loop () : Unit =
- if m > 1 then
- result = result*m
- m = m-1
- loop()
- loop()
- result
Loop (mutable data)
- def factorial (n:Int) : Int =
- val result = 1
- var m = n
- while m > 1 do
- result = result * m
- m = m - 1
- result
# <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-book fa-stack-1x fa-inverse"></i></span> Tail Call Optimization - Many compilers implement _tail-call optimization_ - overwrite existing activation record instead of creating new - Recursive calls must be _tail-recursive_ - Includes _mutual recursion_ - `f` calls to `g`, which calls back to `f` ---
* Time complexity $O(n)$ (no penalty for creating activation records) * Space complexity $O(1)$