next up previous contents index
Next: Iteration on terms Up: Programming Concepts Previous: Alternatives   Contents   Index

Subsections

Iteration on lists


Description

This concept is used to perform some action on each element of a list. There are two implementations given here. The first uses the do loop of ECLiPSe, the second uses recursion to achieve the same purpose. In the do loop, the foreach keyword describes an action for each element of a list. The first argument (here X) is a formal parameter of the loop. At each iteration, it will be bound to one element of the list. The second argument is the list over which we iterate.

It is a matter of style whether to use the first or second variant. For simple iterations, the do loop is usually more elegant. We can also often use it inline, and avoid introducing a new predicate name just to perform some iteration.

Parameters

L
a list

Schema

/* version 1 */

:-mode iteration(+).
iteration(L):-
        (foreach(X,L) do
            q(X)
        ).

/* version 2 */

:-mode iteration(+).
iteration([]).
iteration([H|T]):-
        q(H),
        iteration(T).

Comments

If we want to scan several lists in parallel, we can use multiple foreach statements in the same do loop. The following code fragment calls predicate q for the first elements of list L and K, then for the second elements, etc.
:-mode iteration(+,+).
iteration(L,K):-
        (foreach(X,L),
         foreach(Y,K) do
            q(X,Y)
        ).
This requires that the lists are of the same length, otherwise this do loop will fail.

Note that we can put as many parallel operations into a do loop as we want, they are all executed inside one big loop. We can of course also nest do loops so that one loop is executed inside another loop.

The foreach operator can also be used to create a list in a do loop. This is shown in the transformation concept.

Very often, we have to pass additional parameters into the do loop. We do this with the param parameter, which lists all variables from outside the loop that we want to use inside the loop. A variable which is not mentioned as a param argument, is unbound inside the loop. Normally, this will create a warning about a singleton variable inside a do loop. The following code fragment shows the use of param to pass variables A, B and C to the call of predicate q.

:-mode iteration(+,+,+,+).
iteration(L,A,B,C):-
        (foreach(X,L),
         param(A,B,C) do
            q(X,A,B,C)
        ).


Example

% set the group fields inside the interfaces for each interface
:-mode set_group_of_interfaces(+,+).
set_group_of_interfaces(L,Interfaces):-
        (foreach(group with [type:Type,
                             name:Name,
                             interface:I],L),
         param(Interfaces) do
            find_interface(I,Interfaces,Interface),
            set_group_of_interface(Type,Name,Interface)
        ).
Here we use the information that each member of the list L is a term group/4 to replace the formal parameter with a term structure where we access individual fields directly. Also note that the body of the loop may contain more than one predicate call.
next up previous contents index
Next: Iteration on terms Up: Programming Concepts Previous: Alternatives   Contents   Index
Warwick Harvey
2004-08-07