0
votes

It is interesting for me if there is any built-in tool, in Prolog, that would work for the following example:

parentRole(X,Y,Z):- parent(X,Y), male(X), !, Z=='father', !.
parentRole(X,Y,Z):- parent(X,Y), Z=='mother'.

I want the rule parent(X,Y) to stop the program (+return false) if parent(X,Y) failed, in rule #1, else go on as usually.

This way I'd be able to write:

parentRole(X,Y,Z):- parent(X,Y), male(X), !, Z=='father', !.
parentRole(X,Y,Z):- Z=='mother'.

Suppose facts are:

parent(myMom, i) male(i)

I expect for the scope:

parentRole(notMyMom, i, 'mother')

the program to stop and return false, but in the real, it fails at parent(X,Y) in the 1st rule, and tries to satisfy the 2nd, and it return true as Z=='mother'

Thanks.

2
@TomasBy For example, when i call parentRole(notMyFather, me, 'mother'), I expect the first rule to stop the program, but actually it tries the 2nd one and it returns true. - Postica Ðenis
Not sure but i think you want this for a specific parents \+ parent(a,b),!. Means if your database does not contain any specific a,b then simply stop it. - Luai Ghunim

2 Answers

0
votes

So you want

parentRole(X,Y,Z) :-
  ( parent(X,Y) ->
    ( male(X) -> Z == 'father'
    ; Z == 'mother' ).
  ; fail ).

which is the same as

parentRole(X,Y,Z) :-
  parent(X,Y),
  ( male(X) -> Z == 'father' ; Z == 'mother' ).

Now your example fails, as expected.

Your comment: try this formatting

parentRole(X,Y,Z) :-
  ( parent(X,Y) ->
    ( male(X) ->
      ( Z == 'father' ->
        write('father')
      ; fail )
    ; ( Z == 'mother' ->
        write('mother')
      ; fail ) )
  ; fail ).
0
votes

It makes sense to define a separate rule that verifies the gender.

parentRole(X, Y, Z) :- parent(X, Y), parentGender(X, Z).

parentGender(X, 'father') :- male(X).
parentGender(X, 'mother') :- \+ male(X).

parentRole now only has one rule, so it will fail immediately if parent fails.