Page 1 of 1

Semicolon and parentheses in clause body

Posted: 11 Jan 2016 13:23
by Ferenc Nagy
Hi,
Here is code fragment containing bla-bla(branch-1;branch2 ) finish1;catch_all :

Code: Select all

predicates     onMouseDown : window::mouseDownListener. % Original clause clauses     onMouseDown(_Source, Point, _ShiftControlAlt, _Button) :-        Point = pnt(X0,Y0),        X = X0-x, Y = Y0-d,        X>0, Y>0,        X<field, Y<field,!,        I = X div cell_size,        J = Y div cell_size,        (         cell(step,I,J),         retract(cell(step,I,J)),         aliveN := aliveN-1,         showXY(I,J,empty),!;         assert(cell(step,I,J)),         aliveN := aliveN+1,         showXY(I,J,life)        ),        integerControl1_ctl:setInteger(aliveN);        succeed.
Is the above code a shortening of three statements below?

Code: Select all

%1  onMouseDown(_Source, Point, _ShiftControlAlt, _Button) :-        Point = pnt(X0,Y0),        X = X0-x, Y = Y0-d,        X>0, Y>0,        X<field, Y<field,!,        I = X div cell_size,        J = Y div cell_size,         cell(step,I,J),         retract(cell(step,I,J)),         aliveN := aliveN-1,         showXY(I,J,empty),!,        integerControl1_ctl:setInteger(aliveN),!. %2 onMouseDown(_Source, Point, _ShiftControlAlt, _Button) :-        Point = pnt(X0,Y0),        X = X0-x, Y = Y0-d,        X>0, Y>0,        X<field, Y<field,!,        I = X div cell_size,        J = Y div cell_size,         assert(cell(step,I,J)),         aliveN := aliveN+1,         showXY(I,J,life)        integerControl1_ctl:setInteger(aliveN),        !. %3 onMouseDown(_Source, Point, _ShiftControlAlt, _Button) :-        succeed.
The original clause is indeed shorter than the 3-clause version but it is not transparent for me.
I remember from the manual that ";" means "or" but I do not remember such usage of pairs of parentheses within a clause body.

Posted: 11 Jan 2016 21:39
by Thomas Linder Puls
and (,) has higher precedence than or (;).

Parentheses are used to circumvent/control the precedence.

So

Code: Select all

A and B or C and D
is the same as

Code: Select all

(A and B) or (C and D)
or

Code: Select all

AB or CD where     AB is A and B     CD is C and D
On the other hand

Code: Select all

A and (B or C) and D
is

Code: Select all

A and BorC and D where     BorC is B or C

When do you use more clauses and when do you use semicolons?

Posted: 12 Jan 2016 8:05
by Ferenc Nagy
Thomas,
What is your practice? When do you use separated clauses for the same predicate, and when do you merge the clauses into an single clause containing and+or operators?

Code: Select all

clauses   % Written as two clauses   alfa(A,B,_,_) :-   A, B. alfa(_,_,C,D) :-   C, D.   % Merged in a single clause using and+or alfa(A,B,C,D) :-  (A and B) or (C and D).   % Merged in a single clause using command and semicolon alfa(A,B,C,D) :-  (A,B) ; (C,D).  
When do you recommend the first coding style, and when shall be the second and third coding lookouts better?

Posted: 12 Jan 2016 9:58
by Thomas Linder Puls
I would never use an outermost or:

Code: Select all

p :- A or B.
in favor of

Code: Select all

p :- A. p :- B.
But if the or is not on outermost level, I could use is:

Code: Select all

p :- A, (B or C), D.
Then it can be preferable to repeating code:

Code: Select all

p :- A, B, D. p :- A, C, D.
But in many/most cases I will actually prefer an auxiliary predicate:

Code: Select all

p :- A, q, D. q :- B. q :- C.
In general, I use or rarely, and I mainly use it for two purposes:
  • A logical operator in a condition (but here the I often use orelse instead)
  • A nondeterministic choice point
Logical operator examples (I actually prefer orelse here):

Code: Select all

if A < 10 or A > 100 then ...   foreach X in L and (X < 10 or X > 100) do ...

Nondeterministic choice point examples

Code: Select all

clauses     p(....) = R :-         ... % lot of calculation         (R = A or R = B). % two results (nondeterministic)   foreach X in L1 or X in L2 or X = 17 do ...
Furthermore, I always write or in favor of ;, because the difference between or and and is much more significant than the graphical difference between ; and ,.

Or vs. orelse

Posted: 12 Jan 2016 11:56
by Ferenc Nagy
Thank you, Thomas:
The expression

Code: Select all

a(...) or b(...)
always evaluates b(...) which is in general needless if a(...) succeeds and may result a runtime error within b(...). The evaluation of b(...) is necessary after successful a(...) only if a side-effect of b(...) [e. g. setting a fact like b_result:=true or b_result:=false] is required for later usage.
The expression

Code: Select all

a(...) orelse b(...)
always evaluates b(...) only if b(...) fails so it saves time and avoids some runtime errors.

Posted: 12 Jan 2016 13:25
by Paul Cerkez
my half cent perspective:

I never use the logical operators AND, OR within a clause to execute two different actions/results as they can be really problematic when trouble shooting.

I always use extra clauses. (call it a personal preference :-) )

in the case of a(...) OR b(...) I would use what Thomas describes
I would never use an outermost or:

p :- A or B.

in favor of

p :- A.
p :- B.

But if the or is not on outermost level, I could use is:

p :- A, (B or C), D.

Then it can be preferable to repeating code:

p :- A, B, D.
p :- A, C, D.
If a(...) succeeds, b(...) never gets evaluated. If a(...) fails, the b(...) is active. Any code that may be duplicated in a(...) and b(...) I just put into a 'sub clause' if it is more than a few lines.

p(...):- a(..., p1, ...), !.
p(...):- b(..., p1, ...), !.
p1(...):- %common code

********************
At one time, it was also explained that when the compiler created the object code, it effectively treated the embedded ORs as separate clauses anyway. That was back in 5.x, don't know if it still works that way in 7.x

P.

Re: Or vs. orelse

Posted: 12 Jan 2016 15:03
by Thomas Linder Puls
Ferenc Nagy wrote:Thank you, Thomas:
The expression

Code: Select all

a(...) or b(...)
always evaluates b(...) which is in general needless if a(...) succeeds and may result a runtime error within b(...).
That is fortunately not true.

The evaluation of A or B consist of creating a backtrack point to B and then evaluating A. B will be evaluated only when/if backtracking to it. orelse removes the backtrack point if A succeeds, so in an orelse failure in A will backtrack to B, but A orelse B does not leave a backtrack point after the construction.

Shortcut logical operators in other programming languages

Posted: 13 Jan 2016 8:05
by Ferenc Nagy
The new Visual Basic contains the orelse operator https://msdn.microsoft.com/hu-HU/library/ea1sssb2.aspx.
If either or both expressions evaluate to True, result is True. The following table illustrates how result is determined.
This language does not know the backtracking which is the unique feature of all Prolog versions.

When I was learning the Fortran language in the 1970-s, its manuals did not contain whether the B function is called if the result of determines the

Code: Select all

EAND=A(X,Y).AND.B(X,Y)
and the

Code: Select all

EOR=A(X,Y).OR.B(X,Y)
expressions, respectively.
The later FORTRAN90 had compiler options allowing xor prohibiting the partial evaluation of logical expressions. I wrote the program http://franknagy.atw.hu/Angol/Beatrice.htm using FORTRAN 90 during the years 2003..2005 .