0

Consider the Prolog predicated p(integer),q(integer),r(integer) with the flow model (o) and the predicate s:

p(1). q(1). r(1).
p(2). q(2). r(2).
s:-!,p(X),q(Y),r(Z),write(X,Y,Z),nl.

Give the result of the following goal: s. Justify the answer.

The result is 111,112,121,122,211,212,221,222. I have seen that the cut has no effect if it is at the beginning of a clause. Is this true?

false
  • 10,264
  • 13
  • 101
  • 209

2 Answers2

1

the cut has no effect if it is at the beginning of a clause."

Not exactly. That will depend on whether such predicate has other clauses or not.

Moreover:

  • the predicate write is unary and it cannot be called with three arguments.
  • it is better to group the clauses in the definition of the each predicate.

The correct program would be:

p(1). p(2).
q(1). q(2).
r(1). r(2).

s :- !, p(X), q(Y), r(Z), writeln(X-Y-Z).

Indeed, for this program, the cut has no effect. However, consider the following new version of the program.

p(1). p(2).
q(1). q(2).
r(1). r(2).

s :- !, p(X), q(Y), r(Z), writeln(X-Y-Z).
s :- writeln(here).                       % <= this clause will not be executed!

In this case, the cut in the first clause of predicate s will prevent the execution of the second one.

slago
  • 5,025
  • 2
  • 10
  • 23
0

"the cut has no effect if it is at the beginning of a clause"

This is not true (well, it is here, but accidentally).

The cut means "do not backtrack towards the left of here, instead fail the predicate".

As a consequence, if there are additional clauses coming (lexcially) after the current one, this means "commit to the current clause of the predicate, disregard any further ones".

You can also read it as a "guard-action" separator, performing "first guard wins" logic, where the corresponding guarded action (and only that one) is run on guard success:

head1 :- guard1,!,action1.
head2 :- guard2,!,action2.
head3 :- guard3,!,action3.
head4 :- else_action.

For s/0, there is effectively an empty guard before !, so no guard-testing occurs, just commitment to the current clause. But there is only one clause for s/0, so committing does nothing.

David Tonhofer
  • 14,559
  • 5
  • 55
  • 51