Предикаты возвращаются. пролог - PullRequest
0 голосов
/ 18 сентября 2011

Итак, у меня есть предикат, который возвращает true несколько раз.

% true returns several times and i need to press ';'
?- get_all_transformed_moves.
true ;
true ;
true.

Есть ли у пролога swi какой-то метод, который может помочь мне запустить этот предикат без ввода ';'?

% Wished version 
?- get_all_transformed_moves.
true.

Ответы [ 3 ]

2 голосов
/ 19 сентября 2011

Рассмотрим следующее:

likes(prolog).
likes(haskell).
likes(erlang).

likes_something:-
    likes(_Something).

если теперь вы спросите:

?- likes_something.

вы получите

true ;
true ;
true.

это происходит из-за того, что пролог находит три способа удовлетворения предиката likes_something / 0 (с прологом, haskell и erlang), поэтому он трижды отвечает на true.

это не совсем проблема; в любой момент вы можете нажать , и пролог перестанет пытаться найти ответы (это очень удобно, когда результатов много).

то же самое происходит с вашим предикатом: есть три решения и при нажатии; Вы заставляете пролога найти их всех. как предположил Роча, вы можете использовать findall / 3. Например, вы можете написать:

likes_something:-
   findall(X, likes(X), _).

и это вернет только один yes

однако, он не предлагает больше информации, чем предыдущая версия; вместо этого он скрывает тот факт, что есть 3 решения и тратит время, пытаясь найти больше, в то время как ответ не изменится. По этой причине я думаю, что вы должны использовать findall / 3, если вы действительно хотите увидеть результаты:

likes_all(L):-
   findall(X,likes(X),L).

Конечно, решение о том, хотите ли вы увидеть результаты или нет, зависит от вас (или, скорее, от проблемы, которую вы пытаетесь решить: p)

другой вариант - использовать вырез: !/0 например:

likes_something:-
   likes(_Something),
   !.

это остановит пролог от поиска других решений, и вы получите только одно истинное. Обратите внимание, что порезы могут быть хитрыми.

Всего: если вы хотите, чтобы пролог искал все ответы (если вы решили поместить их в список, или у вас есть побочные эффекты в ваших предикатах, или если вы просто хотите его получить): используйте findall / 3

, если вы не хотите иметь возможность искать больше ответов: используйте сокращение (! / 0)

иначе просто нажмите ввод вместо;

0 голосов
/ 19 сентября 2011

Если вы хотите, чтобы предикат выполнялся не более одного раза, то вы можете использовать один раз / 1, предоставленный SWI.

В вашем примере:

?- once(get_all_transformed_moves).
true.
0 голосов
/ 18 сентября 2011

Вы можете использовать предикат findall / 3:

findall (Объект, Цель, Список).Создает список Список всех объектов Объект, которые удовлетворяют поставленной цели.Часто Object - это просто переменная, и в этом случае запрос может быть прочитан как: Дайте мне список, содержащий все экземпляры Object, которые удовлетворяют цели.

Я полагаю, это то, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...