Nested foreach

Discussions related to Visual Prolog
User avatar
Ferenc Nagy
VIP Member
Posts: 289
Joined: 24 Apr 2007 12:26

Nested foreach

Unread post by Ferenc Nagy » 16 Sep 2015 9:51

Hi,
I'd rather start a new thread about the

Code: Select all

foreach...end foreach
construct instead of continue the "universal quantification http://discuss.visual-prolog.com/viewtopic.php?t=14323"
thread.

1) Are
A)

Code: Select all

foreach nondetpred1(X) do      foreach nondetpred2(X,Y) do          foreach nondetpred3(X,Y,Z) do              procbody(X,Y,Z)          end foreach      end foreach end foreach,
and

B)

Code: Select all

foreach nondetpred1(X),      foreach nondetpred2(X,Y),          foreach nondetpred3(X,Y,Z) do              procbody(X,Y,Z)          end foreach      end foreach end foreach,
equivalent?
I mean: Yes, they are.

The

Code: Select all

foreach...end foreach
,

Code: Select all

if then ...else...end if
constructs are newly added to the VIP syntax. I often add the illegal comma before the closing tag:

Code: Select all

foreach nondetpred3(X,Y,Z) do       procbody((X,Y,Z), % <=== syntax error end foreach.
TIA, Regards,
Frank Nagy

Martin Meyer
VIP Member
Posts: 290
Joined: 14 Nov 2002 0:01

Unread post by Martin Meyer » 16 Sep 2015 11:08

To the equivalence question: Every foreach must have its own do. So, A) is a legal construct (provided all used predicates are declared properly), but B) does not compile.

To the comma issue: I am doing this mistake often too. But clearly there belongs no comma. A comma in that place would have the same meaning as an and. Evidently

Code: Select all

foreach nondetpred3(X,Y,Z) do     procbody(X,Y,Z) and end foreach.
does not make sense.

Many regards
Martin

User avatar
Thomas Linder Puls
VIP Member
Posts: 1624
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls » 16 Sep 2015 11:10

B) is syntactically wrong.

But

Code: Select all

foreach nondetpred1(X) do     foreach nondetpred2(X,Y) do         foreach nondetpred3(X,Y,Z) do             procbody(X,Y,Z)         end foreach     end foreach end foreach,
is equivalent to

Code: Select all

foreach     nondetpred1(X),     nondetpred2(X,Y),     nondetpred3(X,Y,Z) do     procbody(X,Y,Z) end foreach,
if that is what you meant.
Regards Thomas Linder Puls
PDC

User avatar
Ferenc Nagy
VIP Member
Posts: 289
Joined: 24 Apr 2007 12:26

Which is the better progarming style

Unread post by Ferenc Nagy » 16 Sep 2015 11:23

Yes I meant so but I forgot the

Code: Select all

do
words.
Which is the better programing style, the nested

Code: Select all

foreach...do..end foreach
or the single

Code: Select all

foreach comma separated list of predicates do short body end foreach
?
TIA, Regards,
Frank Nagy

Martin Meyer
VIP Member
Posts: 290
Joined: 14 Nov 2002 0:01

Unread post by Martin Meyer » 16 Sep 2015 12:56

Surprisingly a difference between the coding variants is, that the 1st variant produces more backtrack points. Below test shows, that 1st variant produces 6 backtrack points, 2nd produces 4, and a 3rd variant using a generator-fail-loop produces also 4.

Code: Select all

class predicates     nondetpred1 : (unsigned X [out])         nondeterm. clauses     nondetpred1(X) :-         X = std::cIterate(2).   class predicates     nondetpred2 : (         unsigned X,         unsigned Y [out])         nondeterm. clauses     nondetpred2(_X, Y) :-         Y = std::cIterate(2).   class predicates     nondetpred3 : (         unsigned X,         unsigned Y,         unsigned Z [out])         nondeterm. clauses     nondetpred3(_X, _Y, Z) :-         Z = std::cIterate(2).   class predicates     procbody : (         unsigned X,         unsigned Y,         unsigned Z). clauses     procbody(X, Y, Z) :-         stdIo::write("(", X, ", ", Y, ", ", Z, " [", programControl::getBackTrackPoints(), "]", ") ").   class predicates     foreach_ : (         function_nd{Type} Gen,         predicate{Type} Body). clauses     foreach_(Gen, Body) :-         Item = Gen(),             Body(Item),             fail.     foreach_(_, _).   clauses     run() :-         stdIo::write("[", programControl::getBackTrackPoints(), "]\n"),         foreach nondetpred1(X) do             foreach nondetpred2(X, Y) do                 foreach nondetpred3(X, Y, Z) do                     procbody(X, Y, Z)                 end foreach             end foreach         end foreach,         stdIo::write("\n---\n"),         foreach             nondetpred1(X),                 nondetpred2(X, Y),                     nondetpred3(X, Y, Z) do                         procbody(X, Y, Z)         end foreach,         stdIo::write("\n---\n"),         foreach_(             {                 = tuple(X, Y, Z) :-                     nondetpred1(X),                         nondetpred2(X, Y),                             nondetpred3(X, Y, Z)             },             { (tuple(X, Y, Z)) :- procbody(X, Y, Z) }).
Regards
Martin

Peter Muraya
VIP Member
Posts: 146
Joined: 5 Dec 2012 7:29

Unread post by Peter Muraya » 16 Sep 2015 17:40

Hi Frank and Martin,
I'm not sure how to interpret the number of backtracking points metric, i.e., whether the more the better or vice versa. I was not even aware of of the predicate programControl::getBackTrackPoints()

In my case, Im often guided by whether there is further processing I need to do after the end foreach or not. If there is, then the I use the first variant; otherwise I use the second one. For example:-

Code: Select all

foreach nondetpred1(X) do     foreach nondetpred2(X,Y) do         foreach nondetpred3(X,Y,Z) do             procbody(X,Y,Z)         end foreach,         do_something(),     end foreach,     do_something_else() end foreach
Mutall Data Management Technical Support

Martin Meyer
VIP Member
Posts: 290
Joined: 14 Nov 2002 0:01

Unread post by Martin Meyer » 16 Sep 2015 19:24

Roughly speaking backtrack points cost space on the run stack. But stack usage is of course not the only measure of all things, when you have to opt for a coding variant.

Best regards
Martin

Peter Muraya
VIP Member
Posts: 146
Joined: 5 Dec 2012 7:29

Unread post by Peter Muraya » 17 Sep 2015 5:17

Thanks Martin
So, you are using programControl::getBackTrackPoints() for optimization purporses; do you ever use it for other reasons?
Mutall Data Management Technical Support

Martin Meyer
VIP Member
Posts: 290
Joined: 14 Nov 2002 0:01

Unread post by Martin Meyer » 17 Sep 2015 8:40

No, I never used programControl::getBackTrackPoints for other than test/info/optimization.

Regards
Martin

Post Reply