Reputation: 91
I am trying to add an element to the front of a doubly-linked list, however, I am getting the right form for the output, but the value of the cycle node says : {content = < cycle >}
when it should just say < cycle >
.
add_head: (float * 'a) -> ('a lcell) ref -> unit
(* The type of linked lists. *)
type 'a llist =
| Nil
| Cons of (float * 'a) * 'a lcell * 'a lcell
and 'a lcell = ('a llist) ref
let add_head x head =
match !(!head) with
|Nil -> head := !(singleton x)
|Cons (e, prev, next) ->
let first = ref (Cons (x, ref Nil, ref !(!head))) in
prev := !first;
head := first
This is what the output should look like:
{contents =
Cons ((3.3, "c"), {contents = Nil},
{contents =
Cons ((1.2, "b"), <cycle>,
{contents = Cons ((2.2, "a"),<cycle>, {contents = Nil})})})}}
This is my output:
{contents =
Cons ((3.3, "c"), {contents = Nil},
{contents =
Cons ((1.2, "b"), {contents =<cycle>},
{contents = Cons ((2.2, "a"), {contents =<cycle>}, {contents = Nil})})})}}
Any help with why this is happening, and what I am not understanding ?
Upvotes: 0
Views: 352
Reputation: 18892
When you write
let first = ref (Cons (x, ref Nil, ref !(!head))) in
you are creating a fresh reference for first, which cannot thus appears later in the list.
Then, when you update prev
with
prev := !first;
you are making prev
point to the content of the new reference. Consequently,
prev
points to a cycle but it is not part of a cycle.
In you want to avoid this indirection, you need to reuse the already existing prev
reference rather than create a new fresh one:
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;;
Then you should get:
# 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})})})}
Upvotes: 1
Reputation: 66803
Here is my take on the problem.
In your function, head
is a reference to a cell. The function should be updating the cell, not the reference to the cell. So when you assign to the head you want to do this:
!head := <new value>
Not this:
head := ref (<new value>)
I wrote some code that follows this pattern, and it gets the answer that you say is correct.
(This is exactly the same as getting the number of *
dereferences right in C. Which is one reason why functional code is so much more pleasant :-)
Upvotes: 0