使用 trampoline 進行無堆疊遞迴(scala.util.control.TailCalls)
在呼叫遞迴函式時,通常會發生 StackOverflowError
錯誤。Scala 標準庫提供 TailCall, 以通過使用堆物件和 continuation 來儲存遞迴的本地狀態來避免堆疊溢位。
來自 TailCalls 的 scaladoc 的兩個例子
import scala.util.control.TailCalls._
def isEven(xs: List[Int]): TailRec[Boolean] =
if (xs.isEmpty) done(true) else tailcall(isOdd(xs.tail))
def isOdd(xs: List[Int]): TailRec[Boolean] =
if (xs.isEmpty) done(false) else tailcall(isEven(xs.tail))
// Does this List contain an even number of elements?
isEven((1 to 100000).toList).result
def fib(n: Int): TailRec[Int] =
if (n < 2) done(n) else for {
x <- tailcall(fib(n - 1))
y <- tailcall(fib(n - 2))
} yield (x + y)
// What is the 40th entry of the Fibonacci series?
fib(40).result