DCG扩展:是的坚守忽略?(DCG Expansion: Is Steadfastness igno

2019-07-02 17:57发布

假设我有以下DCG规则:

 factor(X) --> "(", expr(X), ")".

通常,这将被转换为:

 factor(X, A, B) :-
    [40|C] = A, expr(X, C, D), [41|B] = D.

将一个Prolog的系统允许如下翻译它,即
合并unifications到头部和目标是什么?

 factor(X, [40|A], B) :-
    expr(X, A, [41|B]). 

如果DCG扩张不会踏实,也不会被允许
把[41 | B]在EXPR呼叫的第三个参数。

但我想坚定很到位,所以一切都应该是好的?

再见

PS:对于坚定看的一个非正式的定义:
理查德·奥基夫,2009年:
“一词的发明者‘在序言编程坚定’,
我应该是赞成它。 基本上坚定性
意味着你不能强迫一个谓词歧途
通过在输出参数错误地填充“。
http://blog.gmane.org/gmane.comp.ai.prolog.swi/month=20090301

PSS:对于其他DCG翻译见例如最新
DCG标准提案。 附录中包含一个DCG翻译
源代码:
ISO / IEC DTR 13211-3:2006
定子句语法规则
克劳斯Daessler
二〇一二年十一月二十日
N238 DIN草案2012年11月20日

Answer 1:

你的翻译是一个有效的。 它不影响坚定性。 但是,它仍然可能不是非常理想。 但是,这取决于你使用的准确实施。 考虑:

opcl --> "".
opcl --> "(", opcl, ")".

随着Prolog的标志double_quotes设置为chars ,第二个子句现在可能扩大到

opcl1(['('|S0],S) :-
   opcl1(S0,S1),
   S1 = [')'|S].

要么

opcl2(['('|S0],S) :-
   opcl2(S0,[')'|S]).

现在考虑的目标phrase(opcl,"(((())))"

像WAM(例如YAP,SICStus)共同的机器,ZIP(SWI),TOAM小(B):

opcl1

opcl1会简单地测试列表的有效性,使用调用堆栈的过程控制。 如果成功,没有弊细胞将被创建,并调用堆栈将再次为空。 其实,上面的实现是不能检测的目标是确定的,所以他们会留下一个选择点开放。 你可以看到这个在顶层:

?- phrase(opcl,"(((())))").
true ;
false.

这种选择点可以与干净,安全删除call_semidet/1

opcl2

opcl2上需要由GC被回收堆|将创建的四个实例[_“)”。 但他们节省了调用堆栈。 也就是说,将只有尾递归调用这些WAM上非常有效地处理的,最低限度的效率较低的小TOAM和SWI相对昂贵。

当我们考虑与发生,检查执行的事情变得更加昂贵。 在曲的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 = XsXsC一个全新的变量,总是相同的。



文章来源: DCG Expansion: Is Steadfastness ignored?