合法使用(\ +)// 1

fal*_*lse 8 prolog dcg iso-prolog

在语法规则()中,有几个预定义的构造:(',')//2意思是连接,('|')//2意思是交替等.一个由几个但不是所有Prolog系统支持的构造是(\+)//1.

就个人而言,我只是为了使用它而使用它.我从未在其他人编写的代码中看到它.

那么,有合法用途(\+)//1吗?

编辑:,另外,是否有合法的使用(\+)//1在查询中phrase(nt, L)使用L一个非实例变量.

小智 2

\+ 可用于创建不太模糊的语法。使用 \+ 的优点超过 ! 例如, 是 \+ 的某种声明性,因此可以对生成的 DCG 规则进行重新排序。

让我们举个例子,考虑以下语法:

s([X|Y]) --> t(X), s(Y).               % 1
s([])    --> [].                       % 2

t(2)     --> [a,a].                    % 3
t(1)     --> [a].                      % 4
Run Code Online (Sandbox Code Playgroud)

上面的语法非常不明确,例如我对以下输入进行了多次解析:

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
A = [2,1,2] ;
A = [2,1,1,1] ;
etc..
Run Code Online (Sandbox Code Playgroud)

现在假设我想更喜欢 t 的长解析而不是 t 的短解析。我可以通过剪切来做到这一点,如下所示:

t(2)     --> [a,a], !.                 % 5
t(1)     --> [a].                      % 6

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No
Run Code Online (Sandbox Code Playgroud)

不幸的是我无法重新订购。因为执行以下操作不会给出所需的结果。尽管 s(A) 现在以不同的顺序产生结果,但我们又回到了原点,因为语法再次不明确:

t(1)     --> [a].                      % 7
t(2)     --> [a,a], !.                 % 8

?- phrase(s(A),[a,a,a,a,a]).
A = [1,1,1,1,1] ;
A = [1,1,1,2] ;
A = [1,1,2,1] ;
etc...
Run Code Online (Sandbox Code Playgroud)

现在让我们尝试使用 \+ 进行同样的操作。我们可以用以下否定来替换剪切:

t(2)     --> [a,a].                    % 9
t(1)     --> [a], \+ [a].              % 10

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No
Run Code Online (Sandbox Code Playgroud)

现在让我们尝试一下是否可以重新排序。我们重新排序 t//1 的语法规则:

t(1)     --> [a], \+ [a].              % 11
t(2)     --> [a,a].                    % 12

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No
Run Code Online (Sandbox Code Playgroud)

声明性非常有用。这意味着我们可以在从右到左的图表解析器中使用 \+ 以任意顺序选择语法规则。声明性确保图表解析器的自下而上的前向链接产生相同的结果,而与 DCG 规则的输入顺序无关。

然后就可以将 DCG 技术应用到大型自然语言 (NL) 项目中,并且可以很好地扩展。NL 语法可以凭经验调整为决定论。语法越确定,其解析就越高效。原本难以处理的复杂自然语言语法变得可行。

再见