Каковы использования предиката fail в Prolog?

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

4 ответов


элегантное системы обеспечивают 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 перечислить via backtracking - очень подверженная ошибкам активность. Рассмотрим случай:

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

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

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

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


один случай (взято из Программирование логики ограничений с использованием Eclipse) является реализацией not/1:

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

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


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

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

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