我正在尝试深入研究GNU Prolog的行为:
test(X,I,O) :- phrase(X,I,O).
?- test(("a",!,"b"),"ab","").
是否有一种标准的方法来查看短语/3翻译成什么?
根据ISO DCG提案(*),有这样的要求我们会得到expand_term/2。现在我可以用这个来检查:
?- expand_term((foo --> "a", !, "b"),X).
X = (foo([97|A],B):-!,A=[98|B])
这是否告诉我短语/3在我的测试/3中是如何使用的?
(*)ISO/IEC DTR 13211-3:2006
定句语法规则
克劳斯Daessler
2012年11月20日
http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dcgs/dcgsdin121120.pdf
是否有一种标准的方法来查看短语/3翻译了什么?
。定义了phrase/3
的含义,但无法访问背后的实际实现。有几种不同的方法来定义phrase/3
。它可以像在YAP中一样简单:
phrase(P, S0, S) :-
call(P, S0, S).
或者它可以使用expand_term/2
(或类似的东西)。即:
phrase(P, S0, S) :-
expand_term(( pseudont --> P ), ( pseudont(CS0, CS) :- Goal) )),
S0 = CS0,
S = CS,
Goal.
调用Goal
后可以执行最终统一:
phrase(P, S0, S) :-
expand_term(( pseudont --> P ), ( pseudont(CS0, CS) :- Goal) )),
S0 = CS0,
Goal,
S = CS.
并由此引入(依赖于实现的)约定,即扩展的谓词总是在最后一个参数中使用未实例化和未别名的变量来调用,这将允许在存在半文本的情况下尾部递归。
这完全取决于实现者。
这是否告诉我短语/3在我的测试/3中是如何使用的?
不,没有办法知道。
但是,你为什么要问?或者,换句话说:
资源消耗不同但符合
phrase/3
的实现会有什么影响?
这应该是显而易见的。考虑?- phrase([],Xs).
,它不会在YAP的堆上创建任何项,但会在上面的expand_term
扩展中创建任何项。但是,资源消耗超出了现行标准的范围。
变量排序
考虑YAP中规则..., phrase([], Xs, Xs), ...
的主体:Xs
仍然是一个局部变量,而基于expand_term
的短语使其成为全局变量。在许多实现中,这将影响变量的相对顺序。现在,标准在7.2.1中明确声明:
如果X和Y是不相同的变量,则
X term_在Y之前应该是实现相关的
除了在创建排序列表(7.1.6.5)期间,
8.10.3.1 j)排序应保持不变。
这又不是问题,但还是会让人讨厌。
<<h2> NSTO属性/h2>Prolog标准(即第1部分ISO/IEC 13211-1)仅定义NSTO的执行。也就是说,如果在执行过程中发生的所有统一都是NSTO -不受happens -check的约束(见7.3.3)。
现在,考虑您的案例:phrase(("a",!,"b"), Xs, Ys)
。乍一看,这相当于phrase("ab", Xs, Ys)
。但现在考虑假设set_prolog_flag(double_quotes,chars)
?- Xs = [c|_], Xs = Ys, phrase(("a",!,"b"), 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中的Herbrand算法。从本质上讲,它"以任意顺序"非确定性地重写了方程。这里有一个这样的派生:
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.2 g时,一组方程才属于非NSTO。引用7.3.3:
一组方程(或两项)"不受
约束"。发生-检查" (NSTO)如果没有办法继续
通过Herbrand算法的步骤,使得
7.3.2 g发生。
freeze/2 and when/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使用什么作为执行术语,因此确定它的唯一方法是查阅源代码。在这里找到:
http://sourceforge.net/projects/gprolog/短语/3谓词在一个名为expand.pl的文件中定义。它的定义使用'$dcg_trans_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参数中,类似于foo规则。因为这是在调用短语/3时完成的,所以应该没有问题。