функция, которая указывает на себя - PullRequest
2 голосов
/ 09 января 2011

Я потерян в следующем примере на стр. 106 из книги под названием «Разработка приложений с объективным верблюдом».

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 является функцией, которая указывает на себя и, следовательно, выполняет цикл.

Я бы подумал, что значение для l после add_assoc_again ('1', 1) l ;; является функцией

x -> if x = '1' then 1 else nil_assoc x;;

В продолжение, результирующее значение для l после add_assoc_again ('2', 2) l ;; должно быть функцией

x -> if x ='2' then 2 else ( function x -> if x = '1' then 1 else nil_assoc x ) x;;

Я не понимаю, почему результирующее значение для l является функцией, которая указывает на себя, и поэтомупрограмма зависает и зацикливается

Ответы [ 2 ]

3 голосов
/ 09 января 2011

!l не оценивается при вызове add_assoc_again, оно оценивается при вызове функции, созданной вызовом. В этот момент l будет указывать на эту функцию, поэтому вы получаете бесконечный цикл.

2 голосов
/ 09 января 2011

В новой книге 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).

Код продолжается:

# 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

, что очень просто для понимания по сравнению с версией, которой вы пользовались.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...