next up previous index
Next: Array Notation Up: ECLiPSe-specific Language Features Previous: Structure Notation   Index

Subsections


Loop/Iterator Constructs

Many types of simple iterations are inconvenient to write in the form of recursive predicates. ECLiPSe therefore provides a logical iteration construct do/2, which can be understood either by itself or by its translation to an equivalent recursion.

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:

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,Struct)

iterate Goals with X ranging over all elements of Struct. 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 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.

Examples

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


next up previous index
Next: Array Notation Up: ECLiPSe-specific Language Features Previous: Structure Notation   Index

1999-08-06