How to use TailCalls?

后端 未结 2 656
不思量自难忘°
不思量自难忘° 2020-12-14 08:54

If I understand correctly, scala.util.control.TailCalls can be used to avoid stack overflows for non-tail-recursive functions by using a trampoline. The example given in the

2条回答
  •  再見小時候
    2020-12-14 09:02

    This question is more than 6 years old, but the accepted answer doesn't seem to answer the question:

    So my question is how to write a factorial or fibonacci function correctly using TailCalls (yes, I know how to use accumulators to get them tail-recursive)?

    So, here it is:

    object Factorial {
    
      /**
        * Returns the nth factorial
        */
      def apply(n: Long): BigInt = {
        if (n < 0)
          throw new IllegalArgumentException("Can't factorial to an index less than 0")
        else {
          import scala.util.control.TailCalls._
          def step(current: Long): TailRec[BigInt] = {
            if (current <= 0)
              done(1)
            else
              tailcall {
                for {
                  next <- step(current - 1)
                } yield current * next
              }
          }
          step(n).result
        }
      }
    
    }
    
    assert(Factorial(0) == 1)
    assert(Factorial(7) == 5040)
    assert(Factorial(10) == 3628800)
    

    One of the big use-cases for using TailCalls is to do something that is right-fold-like.

提交回复
热议问题