prologprolog-cut

Cut and fail semantics in Prolog


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, !.    

Solution

  • Here are the trees:

    trees

    First Program (inverses the success value of P)

    If the call to P succeeds:

    1. Enter predicate not(P)
    2. Enter clause 1 of predicate not(P)
    3. Call(P) --> Success
    4. Traverse Cut
    5. Call Fail --> Failure
    6. Try to backtrack to find alternate solutions
    7. 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:

    1. Enter predicate not(P)
    2. Enter clause 1 of predicate not(P)
    3. Call(P) --> Failure
    4. Clause 1 results in --> Failure
    5. Try alternate clause 2
    6. Call True --> Success
    7. 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:

    1. Enter predicate not(P)
    2. Enter clause 1 of predicate not(P)
    3. Call(P) --> Failure
    4. Clause 1 results in --> Failure
    5. Try alternate clause 2
    6. Call(P) --> Failure
    7. 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.