问题
Imagine that I have the following knowledge base which gives for each person his first name and his age.
person(mary, 39).
person(john, 24).
person(sandy, 17).
Now, I want to retrieve all the persons that are older than 20 years. Furthermore, I just want to collect their first names and not their age. Here, I want to retrieve mary
and john
.
How to do this generally in Prolog and more specifically in SWI-Prolog?
If we use a variable which is not anonymous, like:
?- person(X, Y), Y > 20.
Prolog will give me the values for both X
and Y
and I do not want Y
.
I cannot use the anonymous variable _
because Prolog cannot link its two instantiations. The following gives an error:
?- person(X, _), _ > 20.
So, how to do this?
回答1:
Why don't you define a predicate
ofintrest(X):- person(X,Y),Y>20.
an query
ofintrest(X).
If you don't want to define a predicate you could also use double negation
person(X,_) ,\+(\+ (person(X,Y), Y>20))
回答2:
This answer directly follows up on this previous answer by @danielp.
With the prolog-toplevel of swi-prolog you can have either one:
show answer substitutions of all variables (default)
do not show answer substitutions for variables like
_A
For detailed information, read the manual of the Prolog processor you are using!
For SWI: Environment Control (Prolog flags). current_prolog_flag/2. set_prolog_flag/2.
stefan@Lenovo ~ $ swipl Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.15) ... ?- current_prolog_flag(toplevel_print_anon, Flag). % get default Flag = true. ?- _A = 1. _A = 1. ?- _A = 1, X = _A. _A = X, X = 1. ?- set_prolog_flag(toplevel_print_anon, false). % toggle flag true. ?- current_prolog_flag(toplevel_print_anon, Flag). Flag = false. ?- _A = 1. % watch out! true. ?- _A = 1, X = _A. X = 1. ?- set_prolog_flag(toplevel_print_anon, true). % restore flag true. ?- current_prolog_flag(toplevel_print_anon, Flag). Flag = true. ?- _A = 1. _A = 1. ?- _A = 1, X = _A. _A = X, X = 1.
回答3:
You can define a predicate as already posted in CAFEBABE's answer.
Alternatively, you can also give a name that starts with _
to variables whose values should not appear in the answer (as you already noted, occurrences of _
are always distinct variables):
person(X,_Age), _Age > 20.
Update: This is specific to the Prolog implementation. It works for SICStus, but not for SWI by default (see repeat's answer).
来源:https://stackoverflow.com/questions/34892545/prolog-in-a-query-how-to-put-a-condition-on-a-variable-that-i-do-not-want-in-t