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)
在上面的代码段中,第一个版本给出了堆栈溢出异常 而第二个工作正常。这两者有什么区别? 它们似乎功能相同,但显然没有。
答案 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。
绑定到b
和c
的闭包延迟了对测试的每个分支的评估,直到您通过调用它们强制执行。
在资源方面,闭包不是免费的:除非编译器找到优化它们的方法,否则每次评估它们时都需要分配内存。