?-foreach(I in [1,2,3],format("~d ",I)).
1 2 3
?-foreach(I in 1..3,format("~d ",I)).
1 2 3
?-foreach(I in 3..-1.. 1,format("~d ",I)).
3 2 1
?-foreach(F in 1.0..0.2..1.5,format("~1f ",F)).
1.0 1.2 1.4
|?-foreach(T in ([a,b],1..2),writeln(T))
a,1
b,2
|?-foreach((A,N) in ([a,b],1..2),writeln(A=N)
a=1
b=2
?-foreach(L in [[1,2],[3,4]], (foreach(I in L, write(I)),nl)).
12
34
?-functor(A,t,10),foreach(I in 1..10,arg(I,A,I)).
A = t(1,2,3,4,5,6,7,8,9,10)
?-foreach((A,I) in [(a,1),(b,2)],writeln(A=I)).
a=1
b=2
The power of foreach is more clearly revealed when it is used with arrays. The following predicate creates an N x N array, initializes its elements to integers from 1 to N x N, and then prints out the array.
go(N):-
new_array(A,[N,N]),
foreach(I in 1..N,J in 1..N,A[I,J] is (I-1)*N+J),
foreach(I in 1..N,
(foreach(J in 1..N,
[E],(E @= A[I,J], format("~4d ",[E]))),nl)).
In the last line, E is declared as a local variable. In B-Prolog, a term like A[I,J] is interpreted as an array access in arithmetic built-ins, in calls to '@='/2, and in constraints, but is interpreted as the term A^[I,J] in any other context. That is why users can use A[I,J] is (I-1)*N+J to bind an array element, but cannot use write(A[I,J]) to print an element.
As seen in the examples, foreach(T in ([a,b,c],1..3),writeln(T)) and foreach((A,N) in ([a,b,c],1..3),writeln((A=N)), the base foreach can be used to easily iterate over multiple collections simultaneously.