Prolog. In a query, how to put a condition on a variable that I do not want in the results?

拟墨画扇 提交于 2019-12-23 09:10:53

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!