Difference between revisions of "Language Reference/Terms/Foreach"
< Language Reference | Terms
m (Categorized) |
m (subarticle) |
||
(2 intermediate revisions by the same user not shown) | |||
Line 16: | Line 16: | ||
The main (and important) difference is that a <vp>foreach</vp>-term succeeds after the iteration, whereas a fail loop fails. As a result <vp>foreach</vp>-terms can be followed by other terms and they can be properly nested. | The main (and important) difference is that a <vp>foreach</vp>-term succeeds after the iteration, whereas a fail loop fails. As a result <vp>foreach</vp>-terms can be followed by other terms and they can be properly nested. | ||
{{Example| | |||
<vip>foreach L = list::getMember_nd(LL) do | <vip>foreach L = list::getMember_nd(LL) do | ||
write("<< "), | write("<< "), | ||
Line 33: | Line 32: | ||
*The <vp>Body</vp> of a <vp>foreach</vp>-term is a {{lang2|Terms|Cut_Scopes|cut scope}}, so a <vp>cut</vp> meet in the body will not influence the iteration. | *The <vp>Body</vp> of a <vp>foreach</vp>-term is a {{lang2|Terms|Cut_Scopes|cut scope}}, so a <vp>cut</vp> meet in the body will not influence the iteration. | ||
*A <vp>foreach</vp>-term always succeeds (or raises an exception), and no extra variables are bound after the evaluation of a <vp>foreach</vp>-term. Therefore, a <vp>foreach</vp>-term can only be used for its side effects. | *A <vp>foreach</vp>-term always succeeds (or raises an exception), and no extra variables are bound after the evaluation of a <vp>foreach</vp>-term. Therefore, a <vp>foreach</vp>-term can only be used for its side effects. | ||
}} | |||
{{Example| | |||
<vip>clauses | <vip>clauses | ||
p(L) :- | p(L) :- | ||
Line 64: | Line 63: | ||
end foreach, | end foreach, | ||
stdio::write("Finished all lists\n").</vip> | stdio::write("Finished all lists\n").</vip> | ||
}} | |||
<noinclude> | <noinclude>{{LanguageReferenceSubarticle|Terms/Foreach}}</noinclude> |
Latest revision as of 10:37, 12 February 2013
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.
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.
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").