Каковы использования предиката 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(_).
некоторые люди, возможно, не считают этот особенно хороший стиль программирования. :)