Shaopeng Guo
Shaopeng Guo

Reputation: 35

Prolog, about how to form better clauses

I have following clauses:

num_parent(adam, X) :- !, X = 0.  
num_parent(eve, X) :- !, X = 0.  
num_parent(X, 2).  

When I typed the query:

num_parent(eve,X).

It only returns:

X = 0.  

which is what I want.

But when I typed this query:

num_parent(X,0).  

it only returns:

X = adam.

So how can I modify the clauses to make it return:

X = adam;
X = eve.

Thanks

Upvotes: 2

Views: 104

Answers (2)

false
false

Reputation: 10102

First, try to formulate what you want in plain English. You probably want to say:

Everyone has two parents except Adam and Eve who have none.

What about Lilith? Never mind, let's stick to your reading.

num_parent(Person, 2) :-
   dif(Person, adam),
   dif(Person, eve).
num_parent(adam, 0).
num_parent(eve, 0).

As you can see, it is a bit cumbersome to define this: You have to mention each exceptional person twice. Easy to make an error.

With if_/3 available in library(reif) for SICStus and SWI you can write more succinctly:

num_parent(Person, Num) :-
   if_( ( Person = adam ; Person = eve ), Num = 0, Num = 2 ).

And now some uses:

?- num_parent(eve, Num).
   Num = 0.
?- num_parent(X, 0).
   X = adam
;  X = eve
;  false.
?- num_parent(X, 2).
   dif(X, eve), dif(X, adam).
?- num_parent(lilith, 2).
   true.

Upvotes: 4

damianodamiano
damianodamiano

Reputation: 2662

The programs returns only X = adam because you inserted the cut !. The cut is used when you have found the right rules and you don't need to do further evaluations, but it cuts all the other solutions.

In your case

num_parent(adam, X) :- !, X = 0.  
num_parent(eve, X) :- !, X = 0.  
num_parent(_, 2). %replaced num_parent(X, 2) with num_parent(_, 2) to avoid singleton variable

num_parent(X, 0) returns only X = adam.

If you write

num_parent(adam, X) :- X = 0.  
num_parent(eve, X) :- !, X = 0.  
num_parent(_, 2). 

the solution will be X = adam and X = eve, and in this case:

num_parent(adam, X) :- X = 0.  
num_parent(eve, X) :- X = 0.  
num_parent(_, 2). 

the solution will be X = adam, X = eve and false because the query num_parent(X, 0) doesn't unify with num_parent(_, 2).

You can better see this behavior using the tracer.

Upvotes: 0

Related Questions