I'm learning prolog and I've come across the "cut and fail" combination, and from my understanding they could be used as guard clauses. I've tried experimenting with it but it doesn't work as expected.
old(person1).
old(person2).
skilled(person1).
skilled(person2).
skilled(person3).
skilled(person4).
possible_employee(X):-
old(X),!,fail.
possible_employee(X):-
skilled(X).
In the example above, it should "filter out" old
people, but it filters out everyone and returns false when querying for a possible_employee
. Is my code flawed or my understanding of the concept?
(old(X) ; skilled(X)), possible_employee(X)
will do what you want.
member(X, [person1, person2, person3, person4]), possible_employee(X)
will do what you want.
Your predicate filters out solutions. It can't be used in generative fashion, because of the cut. As soon as old(X)
is fulfilled, the predicate possible_employee/1
irrevocably fails, as prescribed. So it must be supplied with some more possibilities, from some outside source. It itself is done at that point.
What your predicate is (re-)implementing, is "not
", \+
.
In Prolog, not
is not "not". It must be read as "can not prove that ...".
Under this reading, the meaning of possible_employee(X)
is, "can't prove old(X)
, and can prove skilled(X)
". But old(X)
with the fresh X
can always be proved, with that knowledge base.
If the clauses order is switched, it completely changes the predicate's meaning. A predicate's (several) clauses are in an implied disjunction, "or":
possible_employee(X):-
skilled(X).
possible_employee(X):-
old(X),!,fail.
means, "can prove skilled(X)
", and nothing else (do you see why?). So then, under
old(person1).
old(person2).
skilled(person1).
skilled(person2).
skilled(person3).
skilled(person4).
possible_employee(X):-
skilled(X).
possible_employee(X):-
old(X),!,fail.
the call possible_employee(X)
should succeed four times, for all the four persons. And it does, even though the two of them are also old/1
.
So you see, the presence of cut changes everything. It makes the predicate's meaning totally dependent on operational semantics.
In logic, A ; B
is the same as B ; A
. But not operationally so.
Bring the cut in, forget the logic, start thinking of operation details of Prolog interpretation.