Equivalence of disjunction operator and definition with several rules
Wouldn't that mean that ;/2 behaves exactly as if we wrote our own helper predicate consisting of two rules?
No. Term-to-body conversion makes the difference.
But first, its (;)/2
which is defined in both 7.8.6 (disjunction) and 7.8.8 (if-then-else) — as the very first sentence in 7.8.6 suggests. For the round brackets around ;
see the note in 7.1.6.6.
So the first question is how it is possible to decide which subclause applies in case you see ( G_0 ; H_0 )
in your program. This does not depend on the instantiation present when calling (;)/2
but rather it depends on the instantiation during term-to-body conversion (7.6.2).
?- G_0 = ( true -> X = si ), ( G_0 ; X = nisi ).
G_0 = (true->si=si),
X = si
; G_0 = (true->nisi=si),
X = nisi.
?- G_0 = ( true -> X = si ), call( ( G_0 ; X = nisi ) ).
G_0 = (true->si=si),
X = si.
In the first query term-to-body conversion replaces within the disjunction G_0
by call(G_0)
and thus
( call( ( true -> X = si ) ) ; X = nisi ) )
will be executed.
In the second query there are two term-to-body conversions once for the entire query and once for the explicit call/1
, but both leave everything as is, and thus
call( ( true -> X = si ; X = nisi ) )
will be executed and the else case is left out.
Further differences due to term-to-body conversion are for cuts and errors due to malformed bodies.
As far as I know, defining
p(X) :- G1 ; G2 .
is the same as defining
p(X) :- G1 .
p(X) :- G2 .
And yes, you're mixing this ;
with the somewhat related but completely different _ -> _ ; _
.