想我必须在今后恢复长时间运行的计算,可以挂起自身的机制:如何使尾recusive方法也可以指本身在非尾递归的方式
sealed trait LongRunning[+R];
case class Result[+R](result: R) extends LongRunning[R];
case class Suspend[+R](cont:() => LongRunning[R]) extends LongRunning[R];
如何运行它们最简单的方法是
@annotation.tailrec
def repeat[R](body: LongRunning[R]): R =
body match {
case Result(r) => r
case Suspend(c) => {
// perhaps do some other processing here
println("Continuing suspended computation");
repeat(c());
}
}
问题是创建这样的计算。比方说,我们要实现尾递归阶乘是暂停其计算每10个循环:
@annotation.tailrec
def factorial(n: Int, acc: BigInt): LongRunning[BigInt] = {
if (n <= 1)
Result(acc);
else if (n % 10 == 0)
Suspend(() => factorial(n - 1, acc * n))
else
factorial(n - 1, acc * n)
}
但是,这并不编译:
error: could not optimize
@tailrec
annotated methodfactorial
: it contains a recursive call not in tail positionSuspend(() => factorial(n - 1, acc * n))
如何留住在非暂停通话尾递归?
仅供参考:'LongRunning'是偏袒单子! – 2013-03-11 17:44:27
@MyseriousDan谢谢,这很有趣。实际上,'LongRunning'是对我原来的问题的简化 - 我正在为Scala [scala-conduit](https://hackage.haskell.org/package/conduit) //github.com/petr/scala-conduit)其中'Pipe'自然形成单子。 – 2013-03-11 18:13:17
是的,这种事通常是某种自由monad的实例化。偏袒者有点奇怪,因为它通常表示为核心迁移的thunk,但是否具有'Free [()=> _,R]或Free [ChunkOfData => _,R]'几乎没有什么根本区别。 – 2013-03-11 18:16:28