Пролог конструкции if-then-else: -> vs * -> vs. if_ / 3 - PullRequest
0 голосов
/ 31 октября 2018

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

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

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

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

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

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

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

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

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

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

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

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

pred(X) :-
        (   guard(X) <b>*-></b>
            <b>false</b>
        ;   <b>true</b>
        ).

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

<b>guard(a).</b>

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

?- pred(X).
<b>false.</b>

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

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

?- pred(b).
<b>true.</b>

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

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

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

0 голосов
/ 31 октября 2018

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

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

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

P.S. 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

...