阶乘函数的尾递归实现



我正在阅读杰森的书,不太理解以下程序:

let fact2 i =
    let rec loop accum i =
        if i = 0 then 
            accum
        else
            loop (i * accum) (i - 1)
    in
        loop 1
  1. 如何初始化累积?
  2. 最后两行(即在循环 1 中(是什么意思? 循环有两个参数。 为什么这里只传递一个(即循环 1(。

谢谢!!!

我认为这是

实现中的错误。最后一行应该是

循环 1 i

整数 1 初始化loop函数中的accumi初始化同一函数中的i

请注意,以 let rec loop accum i 开头的行定义了一个函数。因此,accum在调用函数时初始化。这发生在最后一行。正如卡卡杜指出的那样,您的帖子中存在转录错误。最后一行应该说loop 1 i(本质上(将accum初始化为 1。

我认为你在第一行有一个额外的"i"。这使得 fact2 需要一个从未使用过的额外参数。相反,它应该读作:

let fact2 =

最后一行显示"循环 1"通常称为部分应用程序。

Ocaml 通常使用柯里函数,所以另一种思考方式是loop实际上接受一个参数并返回一个函数,而该函数又接受另一个参数并返回一个 int。

在这种特殊情况下,(loop 1)的类型int -> int意味着它采用int并返回intloop的类型int -> int -> int意味着它需要int并返回int -> int。它也可以更明确地写成int -> (int -> int)因为->是右关联。

为了回答另一个问题,accum 通过将 1 传递给 loop 来初始化。

以下是有关咖喱的更多信息: http://en.wikipedia.org/wiki/Currying

当然,按照其他人的建议添加另一个"i"也可以,但是当其他人将其遗漏时,您仍然会感到困惑。

let f x y = ...视为等同于let f = fun x -> fun y -> ...可能会有所帮助

当然,let f x = g xlet f = g相同,只是前者仅在g函数时才有效。

最新更新