Difference between revisions of "Language Reference/Terms/Foreach"
< Language Reference | Terms
m (1 revision(s)) |
m (member_nd -> getMember_nd) |
||
Line 18: | Line 18: | ||
'''Example''' | '''Example''' | ||
<vip>foreach | <vip>foreach L = list::getMember_nd(LL) do | ||
write("<< "), | write("<< "), | ||
foreach | foreach X = list::getMember_nd(L) do | ||
write(" ", X) | write(" ", X) | ||
end foreach, | end foreach, |
Revision as of 13:10, 17 October 2008
ForeachTerm : foreach Term do Term end foreach
Consider the schematic foreach term:
foreach Gen do Body end foreach
Gen is (typically) a nondeterm term. Body is evaluated for each solution of Gen. If/when Gen fails the foreach-term succeeds without evaluating Body. Body must be procedure (or erroneous). Gen and Body are both cut scopes.
The schematic foreach term resembles a fail loop:
Gen, Body, fail
The main (and important) difference is that a foreach-term succeeds after the iteration, whereas a fail loop fails. As a result foreach-terms can be followed by other terms and they can be properly nested.
Example
foreach L = list::getMember_nd(LL) do write("<< "), foreach X = list::getMember_nd(L) do write(" ", X) end foreach, write(" >>\n") end foreach.
LL is supposed to be a list of lists. The outer foreach-loop iterates L through this list, so each L is a list. The inner foreach-loop iterates X through the elements of L.
There are a number of things to notice:
- There is no comma before the keywords "do" and "end foreach".
- The Body of a foreach-term is a cut scope, so a cut meet in the body will not influence the iteration.
- A foreach-term always succeeds (or raises an exception), and no extra variables are bound after the evaluation of a foreach-term. Therefore, a foreach-term can only be used for its side effects.
Example
clauses p(L) :- foreach X = list::getMember_nd(L) do stdio::write(X, "\n") end foreach, stdio::write("Finished\n").
Foreach can be used instead of traditional "fail-loops":
clauses p(L) :- X = list::getMember_nd(L), stdio::write(X, "\n"), fail. p(_L) :- stdio::write("Finished\n").
In this context it is advantageous that Body must be a procedure, because in a "fail-loop" the body may accidentally fail before reaching the fail in the loop. Another advantage is that a foreach loop succeeds when the loop is finished, whereas a fail loop fails, so that execution can continue in the same clause. Also notice that foreach can be properly nested:
clauses p(LL) :- foreach L = list::getMember_nd(LL) do foreach X = list::getMember_nd(L) do stdio::write(X, "\n") end foreach, stdio::write("Finished a list\n") end foreach, stdio::write("Finished all lists\n").