Каковы предикаты сбоя в Прологе?

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

5 ответов

Решение

Элегантные системы обеспечивают 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([]). автоматически потерпит неудачу Нет необходимости вводить дополнительный пункт, который никогда не будет успешным для этой цели.

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

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

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

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

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

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

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

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

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

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

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

Некоторые люди, возможно, не считают этот стиль программирования особенно хорошим.:)

fail / 0 - это специальный символ, который немедленно завершится ошибкой, если пролог встретит его как цель.

fail часто используется вместе с CUT(!) для принудительного выполнения ошибки.

      like(me,X) :- chess(X),!,fail.
like(me,X) :- games(X).
Другие вопросы по тегам