A do-loop corresponds to a call to an auxiliary recursive predicate of the form
do__n(...). do__n(...) :- Goals, do__n(...).
IterationSpecs is one (or a comma-separated sequence) of the following:
fromto(First,In,Out,Last) iterate Goals starting with In=First until Out=Last. In and Out are local variables in Goals.
foreach(X,List) iterate Goals with X ranging over all elements of List X is a local variable in Goals. Can also be used for constructing a list.
foreacharg(X,StructOrArray) iterate Goals with X ranging over all arguments of StructOrArray. X is a local variable in Goals. Cannot be used for constructing a term.
for(I,MinExpr,MaxExpr) iterate Goals with I ranging over integers from MinExpr to MaxExpr. I is a local variable in Goals. MinExpr and MaxExpr can be arithmetic expressions. Can be used only for controlling iteration, ie. MaxExpr cannot be uninstantiated.
for(I,MinExpr,MaxExpr,Increment) same as before, but Increment can be specified (it defaults to 1).
count(I,Min,Max) iterate Goals with I ranging over integers from Min up to Max. I is a local variable in Goals. Can be used for controlling iteration as well as counting, ie. Max can be a variable.
param(Var1,Var2,...) for declaring variables in Goals global, ie shared with the context. CAUTION: By default, variables in Goals are local!
Note that fromto/4 is the most general specifier, but foreach/2, foreacharg/2, count/3, for/3,4 and param/N are convenient shorthands.
Syntax: The do-operator binds like the semicolon, ie. less than comma. That means that the whole do-construct should always be bracketed.
Unless you use :-pragma(noexpand) or :-dbgcomp, the do-construct is compiled into an efficient auxiliary predicate named do__nnn, where nnn is a unique integer.
% iterate over list foreach(X,[1,2,3]) do writeln(X). % maplist (foreach(X,[1,2,3]), foreach(Y,List) do Y is X+3). % sumlist (foreach(X,[1,2,3]), fromto(0,In,Out,Sum) do Out is In+X). % reverse list (foreach(X,[1,2,3]), fromto([],In,Out, Rev) do Out=[X|In]). (foreach(X,[1,2,3]), fromto([],In,[X|In],Rev) do true). % iterate over integers from 1 up to 5 for(I,1,5) do writeln(I). count(I,1,5) do writeln(I). % make list of integers [1,2,3,4,5] (for(I,1,5), foreach(I,List) do true). (count(I,1,5), foreach(I,List) do true). % make a list of length 3 (foreach(_,List), for(_,1,3) do true). (foreach(_,List), count(_,1,3) do true). % get the length of a list (foreach(_,[a,b,c]), count(_,1,N) do true). % actually, the length/2 builtin is (almost) length(List, N) :- (foreach(_,List), count(_,1,N) do true). % filter list elements (foreach(X,[5,3,8,1,4,6]), fromto(List,Out,In,[]) do X>3 -> Out=[X|In] ; Out=In). % iterate over structure arguments (foreacharg(X,s(a,b,c,d,e)) do writeln(X)). % collect args in list % (bad example, use =.. if you really want to do that!) (foreacharg(X,s(a,b,c,d,e)), foreach(X,List) do true). % collect args reverse (foreacharg(X,s(a,b,c,d,e)), fromto([],In,[X|In],List) do true). % or like this: S = s(a,b,c,d,e), functor(S, _, N), (fromdownto(N,I,0), foreach(A,List), param(S) do arg(I,S,A)). % The following two are equivalent foreach(X,[1,2,3]) do writeln(X). fromto([1,2,3],In,Out,[]) do In=[X|Out], writeln(X). % The following two are equivalent count(I,1,5) do writeln(I). fromto(0,I0,I,5) do I is I0+1, writeln(I). % Two examples for nested loops. Print all pairs of list elements: Xs = [1,2,3,4], ( foreach(X, Xs), param(Xs) do ( foreach(Y,Xs), param(X) do writeln(X-Y) ) ). % and the same without symmetries: Xs = [1,2,3,4], ( fromto(Xs, [X|Xs1], Xs1, []) do ( foreach(Y,Xs1), param(X) do writeln(X-Y) ) ).