我在第106页的以下示例中丢失了标题为使用Objective Camel开发应用程序的书。
let nil_assoc = function x -> raise Not found ; ;
let l = ref nil_assoc;;
let add_assoc_again (k,v) l = l := (function x -> if x=k then v else !l x) ; ;
add_assoc_again ('1',1) l ; ;
add_assoc_again ('2',2) l ; ;
l的结果值是一个指向自身的函数,因此循环。
我原以为add_assoc_again ('1', 1) l ;;
之后l的值是
功能
x -> if x = '1' then 1 else nil_assoc x;;
继续,add_assoc_again ('2', 2) l ;;
之后l的结果值应为
功能
x -> if x ='2' then 2 else ( function x -> if x = '1' then 1 else nil_assoc x ) x;;
我不明白为什么l的结果值是一个指向自身的函数,因此程序挂起并循环
答案 0 :(得分:3)
!l
时, add_assoc_again
不会被评估,当您调用该调用创建的函数时会对其进行评估。此时l
将指向该函数,这就是为什么你得到无限循环。
答案 1 :(得分:2)
新书http://caml.inria.fr/pub/docs/oreilly-book/ocaml-ora-book.pdf中对此代码进行了略微修改,我觉得更清楚:
let nil_assoc = function x -> raise Not_found ;;
let add_assoc (k,v) l = function x -> if x = k then v else l x ;;
val add_assoc : 'a * 'b -> ('a -> 'b) -> 'a -> 'b = <fun>
参数l
显然是('a -> 'b)
签名中的函数add_assoc
,因此,在被调用之前(if测试失败时)不会对其进行求值。 / p>
代码继续:
# let l1 = add_assoc (1, 1) nil_assoc;;
此处l1
相当于fun x -> if x = 1 then 1 else nil_assoc x
# let l2 = add_assoc (2, 2) l1;;
l2
是fun x -> if x = 2 then 2 else (fun y -> if y = 1 then 1 else nil_assoc y) 2
与您提供的版本相比,这一点非常简单。