Эквивалентность оператора дизъюнкции и определения с несколькими правилами

Я только что наткнулся на определение ;/2 в Руководстве по SWI Prolog, в котором говорится:

The `or' predicate is defined as:

Goal1 ; _Goal2 :- Goal1.
_Goal1 ; Goal2 :- Goal2.

Разве это не означало бы, что ;/2 ведет себя точно так же, как если бы мы написали наш собственный вспомогательный предикат, состоящий из двух правил? Я запомнил, что ;/2 было нечистой конструкцией (но, возможно, я смешиваю это с if-then-else), но это определение чисто (хотя и мета-логично).

Семантика ;/2 определена в стандарте ISO в параграфе 7.8.6, но это делается с точки зрения манипулирования текущим состоянием, точками выбора и т. Д.

Эквивалентно ли определение в руководстве SWI определению ISO? Если нет, знаете ли вы пример, в котором они различаются?


person lambda.xy.x    schedule 14.02.2019    source источник
comment
да, вы смешиваете это с _ -> _ ; _.   -  person Will Ness    schedule 14.02.2019
comment
Так что это я неправильно запомнил ... спасибо!   -  person lambda.xy.x    schedule 14.02.2019
comment
Хм, согласно O'Keefe: Craft of Prolog, глава 3.13, ;/2 прозрачен для сокращений (в то время как, например, call (G) непрозрачен). Я считаю, что это тоже поведение, когда мы определяем вспомогательный предикат.   -  person lambda.xy.x    schedule 14.02.2019


Ответы (2)


Разве это не означало бы, что; / 2 ведет себя точно так же, как если бы мы написали наш собственный вспомогательный предикат, состоящий из двух правил?

Нет. Конверсия термина в тело имеет значение.

Но сначала его (;)/2, который определен в обоих 7.8.6 (дизъюнкция) и 7.8.8 (if-then-else), как следует из самого первого предложения в 7.8.6. Относительно круглых скобок вокруг ; см. Примечание в 7.1.6.6.

Итак, первый вопрос - как можно решить, какой подпункт применим, если вы видите ( G_0 ; H_0 ) в своей программе. Это не зависит от экземпляра, присутствующего при вызове (;)/2, а, скорее, зависит от экземпляра во время преобразования термина в тело (7.6.2).

?- G_0 = ( true -> X = si ), ( G_0 ; X = nisi ).
   G_0 =  (true->si=si),
   X = si
;  G_0 =  (true->nisi=si),
   X = nisi.

?- G_0 = ( true -> X = si ), call( ( G_0 ; X = nisi ) ).
   G_0 =  (true->si=si),
   X = si.

В первом запросе преобразование термина в тело заменяется внутри дизъюнкции G_0 на call(G_0) и, таким образом,

( call( ( true -> X = si ) ) ; X = nisi ) )

будет выполнен.

Во втором запросе есть два преобразования термина в тело: один раз для всего запроса и один раз для явного call/1, но оба оставляют все как есть, и, таким образом,

call( ( true -> X = si ; X = nisi ) )

будет выполнен, а случай else будет исключен.

Дальнейшие различия, связанные с преобразованием термина в тело, касаются порезов и ошибок из-за деформированных тел.

person false    schedule 15.02.2019

Насколько я знаю, определяя

p(X) :- G1 ; G2 .

то же самое, что и определение

p(X) :- G1 .
p(X) :- G2 .

И да, вы смешиваете это ; с несколько родственным, но совершенно другим _ -> _ ; _.

person Will Ness    schedule 14.02.2019