A simple example is the traversal of a list
main :- write_list([1,2,3]). write_list([]). write_list([X|Xs]) :- writeln(X), write_list(Xs).which can be written as follows without the need for an auxliliary predicate:
main :- ( foreach(X, [1,2,3]) do writeln(X) ).
The general form of a do-loop is
( IterationSpecs do Goals )and it 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:
Note that fromto/4 is the most general specifier, but foreach/2, foreacharg/2, count/3, for/3 and param/N are convenient shorthands.
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 (construct a new list from an existing list)
(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]). % or: (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). % or: 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). % or: (count(I,1,5), foreach(I,List) do true).
Make a list of length 3
(foreach(_,List), for(_,1,3) do true). % or: (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), (for(I,N,1), 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) ) ).