Check if variable is empty or filled

9.5k views Asked by At

I have the following problem:

prolog prog:

man(thomas, 2010).
man(leon, 2011).
man(thomas, 2012).
man(Man) :- once(man(Man, _).

problem:

?- man(thomas).
true ;        %i want only on true even if there are more "thomas" *working because of once()*

?- man(X).
X = thomas ;  %i want all man to be listed *isn't working*

goal:

?- man(thomas).
true ;

?- man(X).
X = thomas ;
X = leon ;
X = thomas ;

I do unterstand why this happens, but still want to get the names of all man. So my solution woud be to look if "Man" is initialized, if yes than "once.." else then... something like that:

man(Man) :- (->check<-,once(man(Man, _)); man(Man, _).

On "check" shoud be the code sniped that checks if the variable "Man" is filled.

Is this possible?

2

There are 2 answers

4
lurker On BEST ANSWER

One way to achieve this is as follows:

man(X) :-
    (nonvar(X), man(X, _)), !
    ;
    man(X, _).

Or, more preferred, would be:

man(X) :-
    (   var(X)
    ->  man(X, _)
    ;   once(man(X, _))
    ).

The cut will ensure only one solution (at most) to an instantiated X, whereas the non-instantiated case will run its course. Note that, with the cut, you don't need once/1. The reason once/1 doesn't work as expected without the cut is that backtracking will still come back and take the "or" condition and succeed there as well.

1
false On
man(X) :-
   setof(t,Y^man(X,Y),_).

Additionally to what you are asking this removes redundant answers/solutions.

The built-in setof/3 describes in its last argument the sorted list of solutions found in the first argument. And that for each different instantiation of the free variables of the goal. Free variables are those which neither occur in the first argument nor as an existential variable – the term on the left of (^)/2.

In our case this means that the last argument will always be [t] which is uninteresting. Therefore the _.

Two variables occurring in the goal are X and Y. Or, to be more precise the variables contained in X and Y. Y is an existential variable.

The only free variable is X. So all solutions for X are enumerated without redundancies. Note that you cannot depend on the precise order which happens to be sorted in this concrete case in many implementations.