Prolog 查看短语/3翻译的标准方式?

Prolog 查看短语/3翻译的标准方式?,prolog,dcg,gnu-prolog,iso-prolog,Prolog,Dcg,Gnu Prolog,Iso Prolog,我试图深入了解GNU序言的行为: test(X,I,O) :- phrase(X,I,O). ?- test(("a",!,"b"),"ab",""). 有没有一个标准的方法来查看/3翻译的是什么短语 根据ISO DCG提案(*),存在以下要求: 我们将有一个扩展条款/2。现在我可以用这个来检查: ?- expand_term((foo --> "a", !, "b"),X). X = (foo([97|A],B):-!,A=[98|B]) 这是否告诉我在我的测试/3中如何使用短语/3

我试图深入了解GNU序言的行为:

test(X,I,O) :- phrase(X,I,O).
?- test(("a",!,"b"),"ab","").
有没有一个标准的方法来查看/3翻译的是什么短语

根据ISO DCG提案(*),存在以下要求: 我们将有一个扩展条款/2。现在我可以用这个来检查:

?- expand_term((foo --> "a", !, "b"),X).
X = (foo([97|A],B):-!,A=[98|B])
这是否告诉我在我的测试/3中如何使用短语/3

(*) ISO/IEC DTR 13211–3:2006
定冠词语法规则
克劳斯·戴斯勒
2012年11月20日

有没有标准的方法来查看/3翻译的是什么短语

否。
短语/3
的含义已定义,但其背后的实际实现无法访问。有几种不同的方法可以定义
短语/3
。它可以简单到:

或者它可以使用
扩展\u term/2
(或者类似的东西)。即:

phrase(P, S0, S) :-
   expand_term(( pseudont --> P ), ( pseudont(CS0, CS) :- Goal) )),
   S0 = CS0,
   S = CS,
   Goal.
它可以在调用
目标后执行最终统一:

phrase(P, S0, S) :-
   expand_term(( pseudont --> P ), ( pseudont(CS0, CS) :- Goal) )),
   S0 = CS0,
   Goal,
   S = CS.
这样就引入了(依赖于实现的)约定,即在最后一个参数中,扩展谓词总是使用未实例化和未关联的变量调用,这将允许在存在文本的情况下使用尾部递归性

这一切都取决于实现者

这是否告诉我在我的测试/3中如何使用短语/3

不,没有办法告诉你

但是,你为什么要问?或者,换言之:

短语/3
的不同但一致的实现会产生什么影响

资源消耗 这应该是显而易见的。考虑<代码> -短语([],Xs).<代码>,在YAP堆中没有创建任何术语,但是对于天真的<代码> ExpExpEngult< <代码> ->进行扩展。但是,资源消耗超出了现行标准的范围

变量排序 考虑YAP中规则
…,短语([],Xs,Xs),…
的主体:
Xs
仍然是局部变量,而基于
扩展项的短语使其成为全局变量。在许多实现中,这会影响变量的相对顺序。现在,标准在7.2.1中明确规定:

如果X和Y是不相同的变量,则
Y之前的X项应取决于实施情况
除了在创建排序列表期间(7.1.6.5,
8.10.3.1 j)订购应保持不变。 所以这也不是问题,但这可能会让人恼火

NSTO属性 Prolog标准(即第1部分ISO/IEC 13211-1)仅定义了NSTO时的执行。也就是说,如果在执行过程中发生的所有统一都是NSTO,则无需进行发生检查(见7.3.3)

现在,考虑你的情况:<代码>短语((“a”,“!”,“b”),Xs,Ys)< /代码>。乍一看,这相当于

短语(“ab”,Xs,Ys)
。但是现在考虑假设

毫无疑问,这个查询应该会失败。但这是NSTO吗?天真地说,我们可以假设这可以由以下内容取代:

?- Xs = [c|_], Xs = Ys, Xs = [a,b|Ys].
这相当于:

?- Xs = [c|_], Xs = [a,b|Xs].
显然,
Xs=[a,b | Xs]
本身就是STO(需要进行检查)。但两者同时也是STO!为了理解这一点,在7.3.2中考虑HeBrand算法。本质上,它以“任意顺序”非确定性地重写方程。这里有一个这样的推导:

          Xs = [c|Zs], Xs = [a,b|Xs].
(7.3.2 f) Xs = [c|Zs], [c|Zs] = [a,b,c|Zs].
(7.3.2 d) Xs = [c|Zs], c = a, Zs = [b,c|Zs].
(7.3.2 g) failure (not unifiable, positive occurs-check)
当然,这种推导是不寻常的。通常,当出现
c=a
时,会立即失败,但算法在这方面是不确定的。只有当所有可能的导数都不导致7.3.2g时,一组方程才是NSTO。引用7.3.3:

一组方程式(或两项)是“不受
如果无法继续进行,则执行检查“(NSTO)
通过Herbrand算法的步骤,使
7.3.2 g发生。 冻结/2和何时/2 这些构造也可能受到影响。虽然现有标准文件目前未涵盖这些影响,但了解潜在影响仍然具有相关性。考虑:

?- freeze(L, (X=1;X=2)), phrase(("a",!,"b"),L).
L = [a, b],
X = 1.
B、 SICStus、SWI、YAP都给出了这个答案。因此,这一削减意义重大



无论如何,感谢您的提问–我只有在回答您的问题时才理解NSTO问题!这显然对DCG翻译的制定方式有一定的影响。

因为ISO DCG没有定义一种方法来确定哪个短语/3用作执行术语,唯一的方法是查阅源代码。在这里可以找到:

短语/3谓词在一个名为expand.pl的文件中定义。其定义使用“$dcg\u trans\u body”/4。我们可以检查一下:

GNU Prolog 1.4.2
By Daniel Diaz
Copyright (C) 1999-2012 Daniel Diaz
| ?- '$dcg_trans_body'(("a",!,"b"), In, Out1, Body).

Body = (!,A=[98|Out1])
In = [97|A]
因此,第一个终端确实合并到In参数中,与
富规则。因为这是在调用短语/3时完成的,所以应该不会有问题。

您使用的是GNU的特定版本吗?我对gprolog 1.4.1和1.4.2的解决方案感兴趣。不,我对这里的NSTO问题不感兴趣。
?- freeze(L, (X=1;X=2)), phrase(("a",!,"b"),L).
L = [a, b],
X = 1.
GNU Prolog 1.4.2
By Daniel Diaz
Copyright (C) 1999-2012 Daniel Diaz
| ?- '$dcg_trans_body'(("a",!,"b"), In, Out1, Body).

Body = (!,A=[98|Out1])
In = [97|A]