I am reading through Learn Prolog Now! 's chapter on cuts and at the same time Bratko's Prolog Programming for Artificial Intelligence, Chapter 5: Controlling Backtracking. At first it seemed that a cut was a straight-forward way to mimic an if-else clause known from other programming languages, e.g.
# Find the largest number
max(X,Y,Y):- X =< Y,!.
max(X,Y,X).
However, as is noted down the line this code will fail in cases where all variables are instantiated even when we expect false
, e.g.
?- max(2,3,2).
true.
The reason is clear: the first rule fails, the second does not have any conditions connected to it anymore, so it will succeed. I understand that, but then a solution is proposed (here's a swish):
max(X,Y,Z):- X =< Y,!, Y = Z.
max(X,Y,X).
And I'm confused how I should read this. I thought !
meant: 'if everything that comes before this !
is true, stop termination including any other rules with the same predicate'. That can't be right, though, because that would mean that the instantiation of Y = Z
only happens in case of failure, which would be useless for that rule.
So how should a cut be read in a 'human' way? And, as an extension, how should I read the proposed solution for max/3
above?
!/0
always succeeds. Therefore, the error in your reasoning stems from confusing the notions of terminating, failing, succeeding and cutting the search tree. This confusion is reflected in the wording "stop termination". To answer your question: A 'human' way to read!/0
is to say: "From here on, I can no longer understand all consequences of what I'm doing." This is because it quickly becomes too hard to reason about programs that contain such impure constructs. – Rushing!
is true, stop keeping in mind any other rules with the same predicate (to continue with, in case of failure) -- and go on with what you've got so far as the one and only truth. so, as you've successfully reached this!
because everything before it was true, the instantiation ofY = Z
only happens in case of success, not failure. – Huberty