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

StackOverflow https://stackoverflow.com/questions/3001825

  •  25-09-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

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

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

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

Ломтик неудачи. Для диагностических целей часто полезно добавлять специально false в ваши программы. Видеть Больше подробностей.

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top