【发布时间】:2013-05-08 12:23:17
【问题描述】:
只是玩延续。目标是创建一个函数,该函数将接收另一个函数作为参数,以及执行量 - 和返回函数,该函数将应用参数给定的次数。
实现看起来很明显
def n_times[T](func:T=>T,count:Int):T=>T = {
@tailrec
def n_times_cont(cnt:Int, continuation:T=>T):T=>T= cnt match {
case _ if cnt < 1 => throw new IllegalArgumentException(s"count was wrong $count")
case 1 => continuation
case _ => n_times_cont(cnt-1,i=>continuation(func(i)))
}
n_times_cont(count, func)
}
def inc (x:Int) = x+1
val res1 = n_times(inc,1000)(1) // Works OK, returns 1001
val res = n_times(inc,10000000)(1) // FAILS
但没有问题 - 此代码因 StackOverflow 错误而失败。为什么这里没有尾调用优化?
我使用 Scala 插件在 Eclipse 中运行它,它返回 线程“主”java.lang.StackOverflowError 中的异常 在 scala.runtime.BoxesRunTime.boxToInteger(未知来源) 在 Task_Mult$$anonfun$1.apply(Task_Mult.scala:25) 在 Task_Mult$$anonfun$n_times_cont$1$1.apply(Task_Mult.scala:18)
附言
几乎是直接翻译的 F# 代码可以正常工作
let n_times_cnt func count =
let rec n_times_impl count' continuation =
match count' with
| _ when count'<1 -> failwith "wrong count"
| 1 -> continuation
| _ -> n_times_impl (count'-1) (func >> continuation)
n_times_impl count func
let inc x = x+1
let res = (n_times_cnt inc 10000000) 1
printfn "%o" res
【问题讨论】:
标签: scala continuations tail-call-optimization