2

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

Penelope
  • 291
  • 6
  • Have you tried drawing the trees representing the clauses and then walking the tree? Once you know how to convert the clauses to trees in your head these kind of questions become self evident. :-) . Some users might prefer the Byrd Box but I find that the Byrd Boxes become hard to work with several nested layers, think recursive calls or predicates with several clauses. – Guy Coder Jan 06 '23 at 09:56
  • 1
    For a similar visualization see [Prolog Visualizer](https://cdglabs.github.io/prolog-viz/#/). While it is nice, the syntax for a query needs a `?` and the Prolog Visualizer does not support cuts. – Guy Coder Jan 06 '23 at 10:05
  • Thanks Guy - it also doesn't support grouped clauses like `(goal1 ; goal2)`. – Penelope Jan 06 '23 at 12:24
  • While not specific to this question you might also like [Useful Prolog references](https://swi-prolog.discourse.group/t/useful-prolog-references/1089) – Guy Coder Jan 06 '23 at 17:55

1 Answers1

4

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.

false
  • 10,264
  • 13
  • 101
  • 209
  • hi @false - so the two forms are equivalent except when used with freeze. Is that a correct understanding of your answer - if yes, I'll mark as solved. – Penelope Jan 06 '23 at 22:00
  • 1
    ... except when used with constraints that produce themselves different answers. The example with `freeze/2` is onesuch. fNote that this is relatively rare. – false Jan 07 '23 at 17:26