注意到函数闭包本质上等同于惰性值可能会有所帮助:
lazy n : 'a Lazy.t <=> (fun () -> n) : unit -> 'a
force x : 'a <=> x () : 'a
所以类型'a llist
等价于
type 'a llist = 'a cell Lazy.t
即,惰性单元格值。
根据上述定义,地图实现可能更有意义
let rec map f lst =
match force lst with
| Nil -> lazy Nil
| Cons (hd,tl) -> lazy (Cons (f hd, map f tl))
将其转换回闭包:
let rec map f lst =
match lst () with
| Nil -> (fun () -> Nil)
| Cons (hd,tl) -> (fun () -> Cons (f hd, map f tl))
与追加类似
let rec append a b =
match force a with
| Nil -> b
| Cons (hd,tl) -> lazy (Cons (hd, append tl b))
变成
let rec append a b =
match a () with
| Nil -> b
| Cons (hd,tl) -> (fun () -> Cons (hd, append tl b))
我通常更喜欢使用lazy
语法,因为它可以更清楚地说明发生了什么。
还要注意,惰性暂停和闭包并不完全等价。例如,
let x = lazy (print_endline "foo") in
force x;
force x
印刷
foo
然而
let x = fun () -> print_endline "foo" in
x ();
x ()
印刷
foo
foo
不同之处在于只force
计算一次表达式的值。