Каковы предикаты сбоя в Прологе? - PullRequest
17 голосов
/ 09 июня 2010

Я не могу придумать ситуацию, когда мне это нужно.

Ответы [ 4 ]

19 голосов
/ 09 июня 2010

Элегантные системы предоставляют false/0 в качестве декларативного синонима для императива fail/0.Пример, в котором это полезно, - когда вы вручную хотите принудительно откатить назад для побочных эффектов, таких как:

?- between(1,3,N), format("line ~w\n", [N]), false.
line 1
line 2
line 3

Вместо false/0, вы также можете использовать любую цель, которая не удалась, например, немного короче:

?- between(1,3,N), format("line ~w\n", [N]), 0=1.
line 1
line 2
line 3

Таким образом, false/0 не является строго необходимым, но довольно приятным.

РЕДАКТИРОВАТЬ : Иногда я вижу новичков, которые хотят заявить, например, «мои отношения»не имеет места для пустого списка ", а затем добавьте:

my_relation([]) :- false.

к их коду.Это не необходимо, и не хороший пример использования false/0, за исключением, например, срезов сбоев, которые генерируются программным путем.Вместо этого сосредоточьтесь на том, чтобы изложить то, что содержит в ваших отношениях.В этом случае просто пропустите весь пункт и определите отношение только для списков, которые не являются пустыми, то есть содержат хотя бы один элемент:

my_relation([L|Ls]) :- etc.

или, если выописывают другие термины в дополнение к спискам, используйте ограничение как:

my_relation(T) :- dif(T, []), etc.

Учитывая только одно (или даже оба) из этих двух предложений, запрос ?- my_relation([]). будетавтоматически терпит неудачу.Нет необходимости вводить дополнительное предложение, которое никогда не сработает для этой цели.

8 голосов
/ 29 января 2013

Явный сбой. fail часто используется вместе с cut: ... !, fail. для принудительного сбоя.

Для всех конструкций. Явное использование fail / false для перечисления посредством обратного отслеживания является очень подверженным ошибкам действием. Рассмотрим случай:

... ( generator(X), action(X), fail ; true ), ...

Таким образом, идея состоит в том, чтобы «делать» действие для всех X. Но что произойдет, если action(X) не получится? Эта конструкция просто продолжается со следующим кандидатом & mdash; как будто ничего не случилось. Таким образом, некоторые ошибки могут оставаться незамеченными очень долго.

Для таких случаев лучше использовать \+ ( generator(X), \+ action(X) ), который не срабатывает, если action(X) не срабатывает для некоторых X. Некоторые системы предлагают это как встроенный forall/2. Лично я предпочитаю использовать \+ в этом случае, потому что \+ немного яснее, что конструкция не оставляет привязки.

Failure-slice. В целях диагностики часто полезно специально добавить false в ваши программы. См. для получения более подробной информации.

3 голосов
/ 10 июня 2010

Другое использование при сбое - принудительное возвращение через альтернативы при использовании предикатов с побочными эффектами:

writeall(X) :- member(A,X), write(A), fail.
writeall(_).

Однако некоторые люди могут не подумать об этом особенно хорошем стиле программирования.:)

2 голосов
/ 09 июня 2010

Один случай (взят из Constraint Logic Programming с использованием Eclipse ) - это реализация not / 1:

:- op(900, fy, not).
not Q :- Q, !, fail.
not _ .

Если Q завершается успешно, сокращение (!) Вызывает второепункт должен быть отброшен, а сбой гарантирует отрицательный результат.Если Q терпит неудачу, то запускается второе условие not.

...