2016-01-20 2 views
4

Представьте, что у меня есть следующая база знаний, которая дает каждому человеку свое имя и возраст.Пролог. В запросе, как поставить условие на переменную, которую я не хочу в результатах?

person(mary, 39). 
person(john, 24). 
person(sandy, 17). 

Теперь я хочу получить всех лиц старше 20 лет. Кроме того, я просто хочу собрать их имена, а не их возраст. Здесь я хочу получить mary и john.

Как это сделать обычно в Prolog и более конкретно в SWI-Prolog?

Если мы будем использовать переменную, которая не является анонимным, как:

?- person(X, Y), Y > 20. 

Пролог даст мне значения для обоих X и Y, и я не хочу Y.

Я не могу использовать анонимную переменную _, потому что Prolog не может связывать свои два экземпляра. Вывод следующего сообщения:

?- person(X, _), _ > 20. 

Итак, как это сделать?

ответ

4

Почему вы не определить предикат

ofintrest(X):- person(X,Y),Y>20. 

-запрос

ofintrest(X). 

Если вы не хотите, чтобы определить предикат можно также использовать двойное отрицание

person(X,_) ,\+(\+ (person(X,Y), Y>20)) 
+0

Спасибо за эти 2 решения. У первого есть недостаток, который я должен изменить в своей базе знаний. Второй - это действительно тот ответ, который я искал. –

2

Вы можете определить предикат, уже опубликованный в CAFEBABE's answer. Кроме того, вы также можете дать имя, которое начинается с _ переменных, значения которых не должны появляться в ответ (как уже отмечалось, вхождения _ всегда являются различные переменные):

person(X,_Age), _Age > 20. 

Update: Это специфична для реализации Prolog. Он работает для SICStus, но не для SWI по умолчанию (см. repeat's answer).

+0

Это решение, возможно, подходит для некоторых версий Prolog, но оно не работает с SWI-Prolog. Там переменные, начинающиеся с _, просто используются для удаления предупреждения, предоставленного компилятором, и их значения отображаются в ответе. В любом случае, ваш ответ может быть эффективным для других реализаций Prolog. –

+1

@MathieuVidal: Вы правы, я использую SICStus, и там он работает так, как я описал. Я не считал, что другие реализации обрабатывают его по-разному. – danielp

+0

s (X): также работает с SWI, но должен быть явно включен. см. мой пост, как это можно сделать. – repeat

5

Этот ответ непосредственно следует за this previous answer от @danielp.

С из вы можете иметь либо один:

  • Показать ответ замены всех переменных (по умолчанию)

  • не показывают замены ответа на переменные, такие как _A

Для получения детальной информации , прочитайте руководство по используемому процессору Prolog!

SWI: Environment Control (Prolog flags). current_prolog_flag/2. set_prolog_flag/2.

 
[email protected] ~ $ 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. 
+0

@MathieuVidal. Prolog toplevel (REPL) ** довольно универсален; это помогает мне делать немыслимое количество операций ввода-вывода - просто путем написания запросов и чтения ответов - вместо использования соответствующего API read_term/write_term. – repeat

+0

@MathieuVidal. Хотите узнать, как ведут себя другие процессоры Prolog (не SWI или SICStus)? – repeat

Смежные вопросы