使用 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