First let's address the initial predicate: the formatting suggests a nested if-then-else, but the parenthesis around the second body group the first true
into the else branch:
?- listing(p).
p(A, B) :-
( cond1(A, B)
-> q(A)
; true,
( cond2(A, B)
-> q(B)
)
; true
).
That's how we end up with the queries starting with true, ...
. The second problem here is that the use of ;
is overloaded: a term of the form G1; G2
is interpreted as a disjunction only if G1
is not of the form (Cond -> Goal)
. Otherwise it is interpreted as if-then-else. Let's look at the different cases:
(true, true -> X=a); X=b
interprets ;
as a disjunction because the outermost functor of the left hand side is the conjunction ,
. Prolog reports the answer subsitution for each branch.
(true -> X=a, true); X=b
: is a disjunction for the same reason
(true -> X=a); X=b
: is an if-then-else because the outermost functor of the left hand side is the if-then operator ->
. Prolog only reports the answer substitution for the true
branch.
Interestingly, when we put the condition into a variable, this seems to not work anymore (on SWI 8):
?- G1 = (true -> (X = a)), (G1 ; X=b).
G1 = (true->a=a),
X = a ;
G1 = (true->b=a),
X = b.
The same goes happens when I wrap G1
into a call/1
:
?- G1 = (true -> (X = a)), (call(G1) ; X=b).
G1 = (true->a=a),
X = a ;
G1 = (true->b=a),
X = b.
If I read the answer to an earlier question correctly, the first one should be different.
I would assume that the different tracing behaviour is that the breakpoints interfere with the detection of if-then-else. My mistake during tracing was to hit enter
to creep but did not realize I needed to enter ;
when the actual answer was reported.