[ 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!
loop_name(Name)
This specifier does not affect the semantics of the loop. It allows to give the loop a name, mainly for debugging purposes. Name must be an atom, and is used as the name of the auxiliary predicate into which the loop may be compiled. The name should therefore not clash with other predicate names in the same module.
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. By default, the name of this predicate is do__nnn (where nnn is a unique integer), unless you have explicitly specified a name using the loop_name(Name) specifier.

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
(123) illegal iteration specifier in do-loop
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