Ваш перевод действителен. На стойкость не влияет. Однако это все равно может быть не очень желательно. Но это зависит от конкретной реализации, которую вы используете. Учитывать:
opcl --> "".
opcl --> "(", opcl, ")".
Если флаг Prolog double_quotes
установлен в chars
, второе предложение теперь может быть расширено до
opcl1(['('|S0],S) :-
opcl1(S0,S1),
S1 = [')'|S].
or
opcl2(['('|S0],S) :-
opcl2(S0,[')'|S]).
Теперь рассмотрим цель phrase(opcl,"(((())))"
.
На обычных машинах, таких как WAM (например, YAP, SICStus), ZIP (SWI), TOAM Jr. (B):
opcl1
opcl1
просто проверит правильность списка, используя стек вызовов для процедурного контроля. В случае успеха никакая cons-ячейка не будет создана, и стек вызовов снова станет пустым. На самом деле, вышеперечисленные реализации не могут определить, что цель определена, поэтому они оставят одну точку выбора открытой. Вы можете увидеть это на верхнем уровне:
?- phrase(opcl,"(((())))").
true ;
false.
Эту точку выбора можно аккуратно и безопасно удалить с помощью _ 8_.
opcl2
opcl2
создаст четыре экземпляра [')' | _] в куче, которые должны быть освобождены сборщиком мусора. Но они сохраняют стек вызовов. То есть будут только хвостовые рекурсивные вызовы, которые очень эффективно обрабатываются в WAM, минимально менее эффективно в TOAM Jr. и относительно дороги в SWI.
Все становится еще дороже, когда мы рассматриваем выполнение с проверкой на наличие событий. В Qu-Prolog он всегда включен, а в SWI, XSB и CX вы можете включить его с помощью такого флага:
?- phrase(opcl,Xs,Xs).
true ;
Xs = ['(',')'|Xs] ;
Xs = ['(','(',')',')'|Xs] ...
?- set_prolog_flag(occurs_check,true).
true.
?- phrase(opcl,Xs,Xs).
true ;
**LOOPS**
SWI не нужно выполнять единственную проверку на наличие opcl1
. Но это происходит для каждого )
в opcl2
.
Таким образом, для этих машин ваш перевод не подходит. Но это может быть интересно для другой машины, где нет отдельного стека вызовов и которая не основана на продолжениях.
звонок // 1
Ваш перевод изменит точное соединение в call//1
. Однако цель в call//1
всегда должна быть написана таким образом, чтобы она была непоколебимой! Иначе разницу можно было увидеть уже при звонке phrase(call(Cont),Xs0,Xs)
! Для соответствующего Cont
это будет то же самое, что phrase(call(Cont),Xs0,XsC), XsC=Xs
Что касается вашей цитаты о стойкости: это очень неформальное определение понятия. В конце концов, что значит «неправильно»?
Лучшее определение стойкости для phrase/3
, о котором я знаю, это:
phrase(NT, Xs0,Xs)
и phrase(NT, Xs0, XsC), XsC = Xs
с XsC
новой новой переменной всегда одинаковы.
person
false
schedule
27.10.2012