Search code examples
prologprolog-toplevel

(gnu) Prolog statement with "or" simple example


I struggle with a rather simple GNU Prolog example:

I have a file (test.pl)

cat(muki).
dog(roti).
frog(frogi).

animal(X) :- dog(X).
animal(X) :- cat(X).

When testing it:

  • Importing via ['test.pl']
  • animal(frogi) returns no, as expected
  • animal(muki) returns yes, as expected
  • animal(roti) returns true ? instead of yes, which is not what I would expect.

As far as I know this means that prolog is capable to solve animal for roti but why it does not return yes, just like before?


Solution

  • Compare with trace/0

    | ?- [user].
    compiling user for byte code...
    cat(muki).
    dog(roti).
    frog(frogi).
    
    animal(X) :- dog(X).
    animal(X) :- cat(X).
    
    user compiled, 6 lines read - 578 bytes written, 11515 ms
    
    (5 ms) yes
    | ?- trace.
    The debugger will first creep -- showing everything (trace)
    
    yes
    {trace}
    | ?- animal(muki).
          1    1  Call: animal(muki) ? 
          2    2  Call: dog(muki) ? 
          2    2  Fail: dog(muki) ? 
          2    2  Call: cat(muki) ? 
          2    2  Exit: cat(muki) ? 
          1    1  Exit: animal(muki) ? 
    
    (2 ms) yes
    {trace}
    | ?- animal(roti).
          1    1  Call: animal(roti) ? 
          2    2  Call: dog(roti) ? 
          2    2  Exit: dog(roti) ? 
          1    1  Exit: animal(roti) ? 
    
    true ? 
    
    (1 ms) yes
    {trace}
    | ?- halt.
    

    Ok, now swap the two animal/1 predicates and trace again

    | ?- [user].
    compiling user for byte code...
    cat(muki).
    dog(roti).
    frog(frogi).
    animal(X) :- cat(X).
    animal(X) :- dog(X).
    
    user compiled, 5 lines read - 578 bytes written, 16421 ms
    
    (12 ms) yes
    | ?- trace.
    The debugger will first creep -- showing everything (trace)
    
    yes
    {trace}
    | ?- animal(roti).
          1    1  Call: animal(roti) ? 
          2    2  Call: cat(roti) ? 
          2    2  Fail: cat(roti) ? 
          2    2  Call: dog(roti) ? 
          2    2  Exit: dog(roti) ? 
          1    1  Exit: animal(roti) ? 
    
    (1 ms) yes
    {trace}
    

    On the second run you can see that a failure was encountered and GNU Prolog had to backtrack. If there is no backtracking and the query is true straightaway, with no alternatives to backtrack through, GNU Prolog will show true. If there is backtracking and ultimately the query succeeds, and there exist alternative paths to backtrack though, then GNU Prolog will show yes and allow you to enter a ; to show other solutions. In this case if you were to enter a semi-colon to show other solutions the only other solution is a failure (try it out!)