Difference between revisions of "Language Reference/Terms/Foreach"

From wiki.visual-prolog.com
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'''
{{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'''
{{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>[[Category:Language Reference Subarticle]]</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.

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").