Prolog - binding of operators

Viewed 129

I am doing an exercise from 'Prolog Programming for Artificial Intelligence' by Ivan Bratko. The exercise says:

Define the operators 'if', 'then', 'else' and ':=', so that the following becomes a legal term:

if X > Y then Z := X else Z := Y

Choose the precedences so that 'if' will be the principal functor.

I am having trouble determining out of the operators 'then' and 'else', which one should have the lower precedence (and bind stronger). My answer to this question was:

:- op(900, fx, if).
:- op(800, xfx, else).
:- op(700, xfx, then).
:- op(600, xfx, :=).

(It is also stated in the book that the '>' operator has a precedence of 700).

I thought that 'then' would bind stronger than 'else', however the answer for this exercise states otherwise:

:- op(900, fx, if).
:- op(800, xfx, then).   
:- op(700, xfx, else).  
:- op(600, xfx, :=).

I am not sure of the rationale behind making 'else' have a lower precedence than 'then'. Any insights are greatly appreciated.

2 Answers

Consider for example, with your definition:

?- write_canonical(if a then b else c).
if(else(then(a,b),c))
true.

and with the definition from the book:

?- write_canonical(if a then b else c).
if(then(a,else(b,c)))
true.

and further, with your definition:

?- write_canonical(if a then (if b then c) else d).
if(else(then(a,if(then(b,c))),d))
true.

and with the definition from the book:

?- write_canonical(if a then (if b then c) else d).
if(then(a,else(if(then(b,c)),d)))
true.

Note in particular that with your definition, if ... then ... else, is sometimes parsed as if(else(..., and sometimes as if(then(...!

/* When working on the creation of constructs requiring operators I like to start with setting all of the operator priority's to 10'1 .

If the construct can be made to work with all of the operators at priority at 10'1 that is ideal . Once that is established then the priority can be changed to accomodate further requirements .

For example the further requirements of if _if_ then _then_ else _else_ are considerations of what should be containable in the _if_ and the _then_ and the _else_ parts .

For example if that is desirable for ; such as if foo ; bar then baz ; qux then the priority will have to be greater than 10'1100 .

For example if that is desirable for , such as if foo , bar then baz , qux then the priority will have to be greater than 10'1000 .

For example if that is desirable for \+ such as if \+ foo then \+ bar then the priority will have to be greater than 10'950 .

For example if that is desirable for = such as if _foo_ = bar then _baz_ = qux then the priority will have to be greater than 10'700 . Those 4 operators are the most important considerations . */

:- op(10'1,'fx','if') .
:- op(10'1,'yfx','then') .
:- op(10'1,'yfx','else') .

if _if_ then _then_ else _else_
:-
_if_ -> _then_ ; _else_
.

if _if_ then _then_
:-
if _if_ then _then_ else false
.

/* -- testing -- */

:- op(10'1,'fy','consider') .
:- op(10'1,'xfy','perform') .
:- op(10'1,'xfy','form') .
:- op(10'1,'xfy','expect') .
:- op(10'1,'xfy','actual') .
:- op(10'1,'xfy','success') .
:- op(10'1,'xfy','fail') .

consider _consider_ perform _perform_ form _form_ expect _expect_
:-
findall(_form_,(_consider_,_perform_),_actual_) ,
(
    _actual_ = _expect_ ->
    writeq((success perform _perform_)) , nl ;
    writeq((failure perform _perform_ expect _expect_ actual _actual_)) , nl
)
.

test
:-
consider
(
    (_a_ = true) ; 
    (_a_ = false)
)
perform
(
    if _a_ then (_z_ = b) else (_z_ = c)
)
form
(
    _z_
)
expect
[
    b ,
    c
]
.

test
:-
consider
(
    (_a_ = true) ; 
    (_a_ = false)
)
perform
(
    if _a_ then (_z_ = b)
)
form
(
    _z_
)
expect
[
    b
]
.

test
:-
consider
(
    (_a_ = true , _b_ = true) ;
    (_a_ = true , _b_ = false) ; 
    (_a_ = false , _b_ = true) ; 
    (_a_ = false , _b_ = false)
)
perform
(
    if _a_ then (if _b_ then (_z_ = c) else (_z_ = d)) else (_z_ = e)
)
form
(
    _z_
)
expect
[
    c ,
    d ,
    e ,
    e
]
.


    /*
    YAP 6.2.2 (x86_64-linux): Sat Sep 17 13:59:03 UTC 2016
I   ?-  \+ (test , \+ true) .
    (success)perform if _131254 then(_131271=b)else(_131271=c)
    (success)perform if _131254 then(_131268=b)
    (success)perform if _131257 then(if _131260 then(_131315=c)else(_131315=d))else(_131315=e)
    yes
    */
Related