It is well known that the following two rules
fruit(X) :- yellow(X).
fruit(X) :- red(X).
can be written more concisely as following using the disjunction ;
.
fruit(X) :- ( yellow(X); red(X) ).
Now, let's look at the following which introduces a cut before the disjunctive group.
test(specific) :- !, ( goal1 ; goal2 ).
test(General) :- goal3.
The idea is that if test(specific)
matches, then test(General)
is not executed.
Question: Is the above equivalent to the following?
test(specific) :- goal1.
test(specific) :- !, goal2.
test(General) :- goal3.
I ask because in the first form, the cut is present before the group consisting of both goals ( goal1 ; goal2 )
, but in the second form it is only present before goal2
, which feels asymmetric and that usually prompts me to check my understanding.
The context of this question is trying to better understand the answer to this question: Implementing cut in tracing meta interpreter prolog
Is the above equivalent to the following?
It all depends on what you mean by equivalent. Apart from clause inspection, there is the following difference:
?- freeze(X,writeq(h(X))), test(X).
which will succeed twice with X = specific
, but only the second version will write out h(specific)
twice.
Here is a variant without side effects:
test1(specific) :- !, ( true ; true ).
test1(_).
test2(specific).
test2(specific) :- !.
test2(_).
?- freeze(X,(Y=a;Y=b)), test1(X).
X = specific, Y = a
; X = specific, Y = a.
?- freeze(X,(Y=a;Y=b)), test2(X).
X = specific, Y = a
; X = specific, Y = b
; X = specific, Y = a.
?- freeze(X,(Y=a;Y=b)), test1(X), Y = b.
false.
?- freeze(X,(Y=a;Y=b)), test2(X), Y = b.
X = specific, Y = b
; false.
In other words, this variation may even make a declarative difference. What would be needed to make this safe, is to test for the appropriate instantiation first.