if-then-else表达式有效,但cond不在ocaml factorial函数中

时间:2017-11-28 22:28:09

标签: if-statement ocaml

let cond (a,b,c) =
    match a with
    | true -> b
    | false -> c

let rec fact n =
    cond (n=0,1, n * fact (n-1))

let rec fact n =
    if n=0 then 1 else n * fact (n-1)

在上面的代码段中,第一个版本给出了堆栈溢出异常 而第二个工作正常。这两者有什么区别? 它们似乎功能相同,但显然没有。

1 个答案:

答案 0 :(得分:1)

除了实际答案之外,引入懒惰的一种可能方法是使用中间函数:

let cond (a,b,c) =
  match a with
  | true -> b ()
  | false -> c ()

val cond : bool * (unit -> 'a) * (unit -> 'a) -> 'a = <fun>

使用此定义,您可以按如下方式定义fact

let rec fact n = 
  cond (n=0, (fun () -> 1), (fun () -> (n * fact (n-1))))

val fact : int -> int = <fun>

每个(fun () -> ...)表达式都会创建一个临时对象,一个闭包,它捕获周围环境中的变量。没有参数的闭包称为thunks。 绑定到bc的闭包延迟了对测试的每个分支的评估,直到您通过调用它们强制执行。 在资源方面,闭包不是免费的:除非编译器找到优化它们的方法,否则每次评估它们时都需要分配内存。