私の Scala アプリには、Future[T] 型の結果を返す関数を呼び出す関数があります。マップされた結果を再帰関数呼び出しで渡す必要があります。これを末尾再帰にしたいのですが、マップ (または flatMap) がそれを行う機能を壊しています。「再帰呼び出しが末尾位置にありません」というエラーが表示されます。
以下は、このシナリオの簡単な例です。呼び出しが末尾再帰になるように (Await.result() で Future の利点を損なうことなく) 変更するにはどうすればよいでしょうか?
import scala.annotation.tailrec
import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
implicit val ec = scala.concurrent.ExecutionContext.global
object FactorialCalc {
def factorial(n: Int): Future[Int] = {
@tailrec
def factorialAcc(acc: Int, n: Int): Future[Int] = {
if (n <= 1) {
Future.successful(acc)
} else {
val fNum = getFutureNumber(n)
fNum.flatMap(num => factorialAcc(num * acc, num - 1))
}
}
factorialAcc(1, n)
}
protected def getFutureNumber(n: Int) : Future[Int] = Future.successful(n)
}
Await.result(FactorialCalc.factorial(4), 5.seconds)