What does the following code do?
not(P) :- P, !, fail.
not(P).
And how does that work differently from the following 2 codes :
not(P) :- P, !, fail.
not(P) :- P, !.
Here are the trees:
First Program (inverses the success value of P
)
If the call to P
succeeds:
- Enter predicate not(P)
- Enter clause 1 of predicate not(P)
- Call(P) --> Success
- Traverse Cut
- Call Fail --> Failure
- Try to backtrack to find alternate solutions
- There is a Cut in the way of backtracking; exit the whole predicate with Failure (The Cut+Fail force failure of the predicate if P succeeds)
If the call to P
fails:
- Enter predicate not(P)
- Enter clause 1 of predicate not(P)
- Call(P) --> Failure
- Clause 1 results in --> Failure
- Try alternate clause 2
- Call True --> Success
- There is nothing more to do; exit the predicate with Success
Second Program (always fails)
If the call to P
succeeds:
Behaviour is exactly the same as for the First Program, exit the whole predicate with Failure.
If the call to P
fails:
- Enter predicate not(P)
- Enter clause 1 of predicate not(P)
- Call(P) --> Failure
- Clause 1 results in --> Failure
- Try alternate clause 2
- Call(P) --> Failure
- There is nothing more to do; exit the predicate with Failure. Actually there is a cut to traverse still but it doesn't do anything.
Trying Program 1
Note that not/1
is already a built-in, but I guess we can override it for this exercise.
?- [user].
|: not(P) :- P, !, fail.
|: not(P).
Warning: user://1:9:
Warning: Singleton variables: [P]
|: % user://1 compiled 0.02 sec, 2 clauses
true.
Okay
?- not(true).
false.
?- not(false).
true.
Looks good.
Trying Program 2
?- [user].
|: not(P) :- P, !, fail.
|: not(P) :- P, !.
|: % user://1 compiled 0.02 sec, 2 clauses
true.
?- not(true).
false.
?- not(false).
false.
Looks good.