tailrec annotation- import scala.annotation.tailrec
- def sumTailRecursive (xs:List[Int]) : Int =
- @tailrec
- def aux (xs:List[Int], result:Int) : Int =
- xs match
- case Nil => result
- case y::ys => aux (ys, y + result)
- aux (xs, 0)
- scala> longList (20).length
- res0: Int = 1048576
- scala> sumTailRecursive (longList (20))
- res1: Int = 1048576
tailrec annotation fails if not optimized- import scala.annotation.tailrec
- def sumTailRecursive (xs:List[Int]) : Int =
- @tailrec
- def aux (xs:List[Int], result:Int) : Int =
- xs match
- case Nil => result
- case y::ys => 1 + aux (ys, y + result) // bogus "1 + ..."
- aux (xs, 0)
- error: could not optimize @tailrec annotated method aux:
- it contains a recursive call not in tail position
- def fib(n:Int) : Long =
- if n <= 1 then n
- else fib(n-1) + fib(n-2)
fib(0) |
fib(1) |
fib(2) |
fib(3) |
fib(4) |
fib(5) |
fib(6) |
fib(7) |
fib(8) |
|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 |
- def fib(n:Int) : (Long, Long) =
- if n <= 1 then (0, n)
- else
- val (a, b) = fib(n-1)
- (b, a+b)
- def fib(n:Int, a:Long=0, b:Long=1) : Long =
- if n == 0 then a
- else if n == 1 then b
- else fib(n-1, b, a+b)
- 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)
- }
- fibHelper(n, 0, 1)
- }
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
Recursive (mutable)
- 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
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
Tail-recursive
- def factorial (n:Int) : Int =
- def loop (m:Int, result:Int) : Int =
- if m > 1 then loop(m-1, m*result)
- else result
- loop(n,1)
Recursive (immutable)
- def factorial (n:Int) : Int =
- def loop (m:Int) : Int =
- if m > 1 then m * loop(m-1)
- else 1
- loop(n)
TODO: attempt to translate into a loop
* Time complexity $O(n)$ (additional penalty for activation records) * Space complexity $O(n)$
* Time complexity $O(n)$ (no penalty for creating activation records) * Space complexity $O(1)$