is it possible to define a circular list in erlang? http://en.wikipedia.org/wiki/Linked_list
first question would be what exactly a circular list mean in erlang? is it with two elements, one element its self and next to it address to the next element, stored in a list?
if so i can say there is a possibility of defining a circular list in erlang. but i need clarification weather is it what i think a circular list is in erlang?
There is no built-in list mechanism to do it. However, you can build one using a tuple holding the elements you've visited or not.
The basic structure is a tuple with two lists: {Old, New}
. When you first start with an empty list, it looks like {[],[]}
. When you fill the list, you fill it in the New
list:
new() -> {[], []}.
insert(X, {Old, New}) -> {Old, [X|New]}.
peek({_Old, [H|_]}) -> X.
To move within the list, what you do is first seek in the New
list, and put the value in the old one:
next({Old, [H|New]}) -> {[H|Old], New}.
That's fine and it works as if we were just discarding old elements. What happens when we hit the end of the list though? We need to fix the function (and also the peek one):
peek({Old, []}) -> hd(lists:reverse(Old));
peek({_Old, [H|_]}) -> X.
next({Old, []}) ->
{[], lists:reverse(Old)}}.
next({Old, [H|New]}) ->
{[H|Old], New}}.
If there's nothing in the list, it crashes. You could also return 'undefined' if you wanted to by special casing it:
next({[], []}) ->
undefined;
next({Old, []}) ->
{[], lists:reverse(Old)}.
next({Old, [H|New]}) ->
{[H|Old], New}.
This then lets you use the function 'next', 'peek' and possibly 'delete' (see below) to do normal stuff. We could also add a 'prev' function to allow backwards browsing:
prev({[], []}) ->
undefined;
prev({[], New}) ->
{lists:reverse(New), Old}.
prev({[H|Old], New}) ->
{Old, [H|New]}.
delete({Old, []}) -> {[], tl(lists:reverse(Old))};
delete({Old,[H|New]}) -> {Old, New};
And that should cover most of it.