Пролог конструкции if-then-else: -> vs *-> vs. if_/3

Как отмечалось в другом ответе Stackru, который я больше не могу найти, этот шаблон часто появляется в практическом коде Prolog:

pred(X) :-
    guard(X),
    ...
pred(X) :-
    \+ guard(X),
    ...

и многие люди пытаются сжать это

pred(X) :-
    (guard(X) ->
    ...
    ;
    ...).

Однако, как мы все знаем, структура стрелок разрушает точки выбора и не логична.

В книге Ульриха Ноймеркеля и Стефана Крала dif / 2 предикат называется if_/3 предлагается монотонно и логично, однако в статье упоминается еще одна конструкция, которая привлекла мое внимание: *->,

*-> Создайте функции в точности так же, как в приведенном выше примере с невыраженной защитой, и, таким образом, он кажется идеальным для моих целей, так как я не хочу иметь условное условие, которое требуется if_/3 и мне наплевать на дополнительные пункты выбора. Если я не ошибаюсь (правка), он предлагает ту же семантику, что и if_/3 но без требования добавления "reification" к предикату условия.

Однако в документации SWI для него говорится, что "эта конструкция используется редко", что мне кажется странным. *-> мне кажется, что это строго лучше, чем -> когда вы пытаетесь сделать чисто логическое программирование. Есть ли какая-либо причина избегать этой структуры, или есть даже лучшая альтернатива всей структуре охранного предложения / отрицательного защитного предложения?

2 ответа

Решение

Давайте попробуем это! Шаблон, который вы даете:

пред (X):-
    (охранник (X) ->
         ...;    ...).

Я сейчас пользуюсь (*->)/2 и заполните "..." следующим образом:

пред (X): -
        (охранник (X) * ->
            ложный; правда).

Далее, как guard/1 Я определяю очевидно чистый предикат:

охранник (а).

Теперь давайте спросим pred/1 самый общий вопрос: есть ли какие-либо решения вообще?

? - пред (X).
ложный.

Итак, согласно предикату, нет термина X такой, что pred(X) это правда.

Но это неправильно, потому что на самом деле существует такой термин:

? - Пред (б).
правда.

По факту, pred/1 имеет бесконечно много решений. Приемлемо ли в такой ситуации, что предикатные состояния вообще отсутствуют? Конечно, потому что ответ был рассчитан очень эффективно, не так ли?

Мы заключаем, что (*->)/2 разделяет важный недостаток (->)/2: Он может неправильно зафиксировать одну из ветвей в тех случаях, когда другая ветвь будет применима, если будут дополнительно созданы только переменные, которые встречаются в условии. Предикат, который зависит от реализации его аргументов таким образом, никогда не может быть чистым, потому что он противодействует монотонному рассуждению, которое мы ожидаем применить к программам с чистой логикой. В частности, с логической точки зрения, так как pred(b) держит, мы ожидаем, что pred(X), который является обобщением pred(b), не должен подвести. Когда это свойство нарушается, вы больше не можете применять декларативную отладку и другие важные подходы, которые позволяют вам более легко понимать, рассуждать о программах Prolog и управлять ими, и которые представляют собой главную привлекательность декларативного программирования в первую очередь.

Вопрос, который вы упомянули, вероятно, что использует if_3/ есть?,

Обычно называемая мягкая управляющая конструкция доступна в нескольких системах Prolog. CxProlog, ECLiPSe, JIProlog, SWI-Prolog и YAP предоставляют его как *->/2 предикат и инфиксный оператор. Ciao Prolog, SICStus Prolog и YAP обеспечивают if/3 Предикат с той же семантикой.

Мое основное использование этой мягкой управляющей конструкции - реализация коиндукции в Logtalk, где она играет критическую роль. За пределами этого случая я редко использую его.

->/2с другой стороны, он широко используется. Неявное сокращение части if является локальным по отношению к конструкции, и ее использование позволяет избежать, как в вашем примере, попытки дважды доказать защиту, что может быть вычислительно дорогостоящим. Это может быть не чисто, но, как и в случае с разрезом, если вы полностью осведомлены о его плюсах и минусах, это полезная управляющая конструкция.

PS Logtalk предоставляет модульные тесты для этой конструкции управления для *->/2 вариант на https://github.com/LogtalkDotOrg/logtalk3/tree/master/tests/prolog/control/soft_cut_2_3 и для if/3 вариант на https://github.com/LogtalkDotOrg/logtalk3/tree/master/tests/prolog/control/if_3

Другие вопросы по тегам