Firstly, iterators are matching-based. No iterator can 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 the iterations unless they are declared local or 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 a looping goal.
Thirdly, no meta terms should be included in iterators or 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 list constructors, the compiler may generate code that has different behavior as interpreted.
Neng-Fa Zhou 2012-01-03