% File : ARRAYS.PL % Author : R.A.O'Keefe % Updated: 8 November 1983 % Purpose: Updatable arrays in Prolog. % In this package an array is represented in the following notation % {1,2,3} is shown initially as % array([1|_1],[2|_2],[3|_3])+0 % where the [1|_1] etc. are lists in which the most recent value for % the element comes last, and the +0 is a zero updates count. % Updating the 2nd element to a 5 for example would make the array into % array([1|_1],[2,5|_2],[3|_3])+1 % Function "list_to_array" converts list e.g. [1,2,3,4] to array in % this format, "array_to_list" converts back. % fetch(+N,+A,-Elem) Fetches Nth element % store(+N,+A,+Elem,+NewA) Stores Elem at Nth element of A giving NewA /* These operations are fully described in "Updatable Arrays in Prolog", R.A.O'Keefe, DAI Working Paper 150. Note that store(Index, Old, Elem, New) sometimes side-effects Old and sometimes doesn't; you cannot rely on Old remaining unchanged. (i.e. uninstantiated arguments in Old may become instantiated.) This is NOT an example of logic programming. For a logic programming solution (with cost O(lgN) rather O(1)) see Trees.Pl. */ array_length(Array+_, Length) :- functor(Array, array, Length). array_to_list(Array+_, List) :- Array =.. [array|Wrapped], un_wrap(Wrapped, List). un_wrap([History|Histories], [Element|Elements]) :- get_last(History, Element), !, un_wrap(Histories, Elements). un_wrap([], []). fetch(Index, Array+_, Element) :- arg(Index, Array, History), get_last(History, Element). get_last([Head|Tail], Element) :- var(Tail), !, Element = Head. get_last([_|Tail], Element) :- get_last(Tail, Element). list_to_array(List, Array+0) :- wrap_up(List, Wrapped), Array =.. [array|Wrapped]. wrap_up([Element|Elements], [[Element|_]|Wrapped]) :- !, wrap_up(Elements, Wrapped). wrap_up([], []). store(Index, Array+Updates, Element, NewArray+NewUpdates) :- functor(Array, array, Length), arg(Index, Array, History), put_last(History, Element), K is Updates+1, !, store(Length, K, NewUpdates, Array, NewArray). store(N, N, 0, Old, New) :- !, Old =.. [array|OldList], un_wrap(OldList, MidList), !, wrap_up(MidList, NewList), New =.. [array|NewList]. store(_, U, U, Array, Array). put_last(History, Element) :- var(History), !, History = [Element|_]. put_last([_|History], Element) :- put_last(History, Element).