Arrays in Prolog

Prolog variables are immutable. for this reason there is no builtin array type.

For Arrays implemented using Prolog OOP check here

Think about it to support backtracking Prolog have keep the state at every point. First arrays can be big and vector operations can involve elements all over the place. So keeping track is not just inefficient, but also very complex.

For this and other reasons Prolog does not support standard type of arrays.

That is all good and stuff, but what if you still need simple small array !?
The obvious way to implement it is to use Lists, but because the access to elements is sequential the implementation will be slow.

Instead we will do it in a more hacky, no-no method, by using Terms instead of Lists. We do that by employing arg and setarg. The difference is that they allow direct access ergo implementation will be fast.

Below you have simple API that support 1D and 2D arrays.

:- initialization(main).

say(X) :- write(X), write('\n').
say(D,X) :- write(D), write(X), write('\n').

ary1d_new(Size,Sym,Ary) :- 
	functor(Ary,a1,Size), 
	forall(arg(X,Ary,_), nb_setarg(X,Ary,Sym)).
ary1d_get(Pos,Ary,Val) :- arg(Pos,Ary,Val).
ary1d_set(Pos,Ary,Val) :- nb_setarg(Pos,Ary,Val).

ary2d_new(Rows,Cols,Sym,Ary) :- 
	functor(Ary,a2,Rows), 
	ary1d_new(Cols,Sym,Row),
	forall(arg(X,Ary,_), nb_setarg(X,Ary,Row)).
ary2d_get(X,Y,Ary,Val) :- arg(X,Ary,Row), arg(Y,Row,Val).
ary2d_set(X,Y,Ary,Val) :- arg(X,Ary,Row), nb_setarg(Y,Row,Val).

main :-
say('1D example : '),
ary1d_new(5,0,A1D),say('new(5) : ', A1D),
ary1d_set(2,A1D,1),say('set(2,1) : ', A1D),
ary1d_get(2,A1D,Val),say('get(2) : ', Val),
say('2D example : '),
ary2d_new(3,3,0,A2D),say('new(3,3) : ', A2D),
ary2d_set(2,2,A2D,1),say('set(2,2,1) : ', A2D),
ary2d_get(2,2,A2D,Val),say('get(2,2) : ', Val),
ary2d_get(X,Y,A2D,1),say('find coord of 1 : ', [X,Y]).

-----

1D example : 
new(5) : a1(0,0,0,0,0)
set(2,1) : a1(0,1,0,0,0)
get(2) : 1
2D example : 
new(3,3) : a2(a1(0,0,0),a1(0,0,0),a1(0,0,0))
set(2,2,1) : a2(a1(0,0,0),a1(0,1,0),a1(0,0,0))
get(2,2) : 1
find coord of 1 : [2,2]
true.

The implementation of 2D array above uses as storage mechanism 1D array for every row.

But there is also possible to use single 1D array for this purpose. In this case to access a cell we would need to transform the 2D coordinate to 1D.

One problem with this is there is no way to guess the dimensions of the 2D array if we use 1D array to represent it. For this reason we will use the first 2 elements of the storage to store those dimensions.

Here is how an implementation will look like :

%% 2D array using 1D storage
a2d_new(Rows,Cols,Sym,Ary) :- 
	Size is Rows * Cols + 2, 
	ary1d_new(Size,Sym,Ary), 
	nb_setarg(1,Ary,Rows), nb_setarg(2,Ary,Cols).
a2d_get(X,Y,Ary,Val) :- 
	arg(2,Ary,Cols), Pos is (X-1) * Cols + Y + 2,
	arg(Pos,Ary,Val).
a2d_set(X,Y,Ary,Val) :- 
	arg(2,Ary,Cols), Pos is (X-1) * Cols + Y + 2,
	nb_setarg(Pos,Ary,Val).
a2d2lst(Ary,Lst) :- Ary =.. [ _,_,_ | Lst].

For Arrays implemented using Prolog OOP check here