[ Control | The ECLiPSe Built-In Predicates | Reference Manual | Alphabetic Index ]

+IterationSpecs do +Goals

Execute Goals iteratively according to IterationSpecs.
+IterationSpecs
a comma-separated sequence of iteration specifiers
+Goal
a goal (atom or compound term)

Description

This is a meta-predicate for writing simple iterations without the need for an auxiliary recursive predicate.

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.

Fail Conditions

Fails if one of the Goals fails, or if two IterationSpecs specify a different number of iterations.

Resatisfiable

No.

Exceptions

(4) instantiation fault
IterationSpecs insufficiently instantiated
(100) accessing a procedure defined in another module
Ill-formed IterationSpecs

Examples

% 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]).

% reverse list (even shorter)
?- (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)).

% iterate over integers from 1 up to 5
?- (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).

% make a list of length 3
?- (foreach(_,List), for(_,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,-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)
	)
    ).


% Find all pairs of list elements and collect them in a result list:

pairs(Xs, Ys, Zs) :-
    (
        foreach(X,Xs),
        fromto(Zs, Zs4, Zs1, []),
        param(Ys)
    do
        (
            foreach(Y,Ys),
            fromto(Zs4, Zs3, Zs2, Zs1),
            param(X)
        do
            Zs3 = [X-Y|Zs2]
        )
    ).


# flatten a 2-dimensional matrix into a list

flatten_matrix(Mat, Xs) :-
	dim(Mat, [M,N]),
	(
	    for(I,1,M),
	    fromto(Xs, Xs4, Xs1, []),
	    param(Mat,N)
	do
	    (
		for(J,1,N),
		fromto(Xs4, [X|Xs2], Xs2, Xs1),
		param(Mat,I)
	    do
	    	X is Mat[I,J]
	    )
	).

See Also

pragma / 1