Firstly, iterators are matching-based. Iterators cannot change a collection, unless the goal of the loop has that effect. For example,
?-foreach(f(a,X) in [c,f(a,b),f(Y,Z)],write(X)).displays b. The elements c and f(Y,Z) are skipped because they do not match the pattern f(a,X).
Secondly, variables are assumed to be global to all of the iterations, unless they are declared local, or unless they occur in the patterns of the iterators. Sometimes, one may use anonymous variables '_' in looping goals, and wrongly believe that they are local. The parser issues a warning when it encounters a variable that is not declared local but occurs alone in a looping goal.
Thirdly, no meta-terms should be included in iterators or in list constructors! For example,
?-D=1..5, foreach(X in D, write(X)).is bad, since D is a meta-term. As another example,
?-C=(X : I in 1..5), L @=[C].is bad since C is a meta-term. When meta-terms are included in iterators or in list constructors, the compiler may generate code that has different behavior as interpreted.
Neng-Fa Zhou 2013-01-25