我正在尝试实现一个在OCaml中返回阶乘的函数,但我不知道我是否真的使用了连续传递样式:
let fact n =
let rec factorial n cont = match n with
| 0 -> cont ()
| _ -> factorial (n-1) (fun () -> cont () * n) in
factorial n (fun () -> 1)
在我看来,我并没有真正推迟计算,只是取代我的代码中的计算。
答案 0 :(得分:4)
嗯,实际上你的代码非常有趣。它不常见,但它是尾递归的,所以它会起作用。我将向您展示做CPS的“通常”方式。通常,您正在使用延续函数从函数返回,这就是为什么以return
为继续命名的原因。此外,通常您从身份函数开始作为延续的初始值。最后,你将继续作为一个程序集,在那里你可以构建答案。
let factorial n =
let rec loop n return = match n with
| 0 -> return 1
| n -> return (loop (n-1) (fun x -> x * n)) in
loop n (fun x -> x)
所以在这个例子中,我传递了一个将会累积的延续,并最终建立答案。
总结一下,有三个简单的规则:
但无论如何,你的功能是一个有趣的解决方案。 aIndeed,你正在使用的是构建一个懒惰的闭包列表。在计算的每个步骤中,您将创建一个闭包,它使用先前的闭包并将其乘以n。当你达到0时,你会调用这个闭包链。所以,这是空间中的O(n),但不是堆栈,而是使用堆。当然,我的解决方案是太空中的O(n)。我只是澄清一下。