使用延续传递样式实现简单的阶乘函数

时间:2014-12-06 00:35:39

标签: ocaml

我正在尝试实现一个在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)

在我看来,我并没有真正推迟计算,只是取代我的代码中的计算。

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)

所以在这个例子中,我传递了一个将会累积的延续,并最终建立答案。

总结一下,有三个简单的规则:

  1. 继续返回
  2. 以身份开始
  3. 更新每一步的续约。
  4. 但无论如何,你的功能是一个有趣的解决方案。 aIndeed,你正在使用的是构建一个懒惰的闭包列表。在计算的每个步骤中,您将创建一个闭包,它使用先前的闭包并将其乘以n。当你达到0时,你会调用这个闭包链。所以,这是空间中的O(n),但不是堆栈,而是使用堆。当然,我的解决方案是太空中的O(n)。我只是澄清一下。

相关问题