Когда вы пишете
let first = ref (Cons (x, ref Nil, ref !(!head))) in
, вы создаете новую ссылку для первого, которая не может, следовательно, появиться позже в списке. Затем, когда вы обновляете prev
с помощью
prev := !first;
, вы заставляете prev
указывать на содержание новой ссылки. Следовательно, prev
указывает на цикл, но он не является частью цикла.
Чтобы избежать этой косвенности, необходимо повторно использовать уже существующую ссылку prev
, а не создавать новую свежую. :
let add_head x head =
match !(!head) with
| Nil -> head := !(singleton x)
| Cons (e, prev, next) ->
let first = Cons (x, ref Nil, !head) in
prev := first;
head := prev;;
Тогда вы должны получить:
# let r= ref (ref Nil);;
# add_head (0., 0) r;;
# add_head (1., 1) r;;
# add_head (2., 2) r;;
# !r;;
{contents =
Cons ((2., 2), {contents = Nil},
{contents =
Cons ((1., 1), <cycle>,
{contents = Cons ((0., 0), <cycle>, {contents = Nil})})})}