26

私の 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)
4

4 に答える 4

0

これは、future を返す別の関数を呼び出す foldLeft ソリューションです。

def factorial(n: Int): Future[Int] =
  (1 to n).foldLeft(Future.successful(1)) {
    (f, n) => f.flatMap(a => getFutureNumber(n).map(b => a * b))
  }

def getFutureNumber(n: Int) : Future[Int] = Future.successful(n)
于 2013-06-09T13:25:44.897 に答える