7

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

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

那么,是否有合法用途(\+)//1

编辑:此外,在带有未实例化变量(\+)//1的查询中是否有合法用途。phrase(nt, L)L

4

2 回答 2

4

\+ 可用于创建不那么模棱两可的语法。使用 \+ 的优势!例如,是 \+ 的某种声明性,因此可以重新排序生成的 DCG 规则。

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

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

t(2)     --> [a,a].                    % 3
t(1)     --> [a].                      % 4

上面的语法是高度模棱两可的,例如我得到了以下输入的多个解析:

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
A = [2,1,2] ;
A = [2,1,1,1] ;
etc..

现在假设我更喜欢 t 的长解析而不是 t 的短解析。我可以通过以下方式进行切割:

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

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No

不幸的是,我无法重新订购。由于执行以下操作不会产生预期的结果。尽管 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...

现在让我们尝试使用 \+。我们可以用下面的否定来代替cut:

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

?- phrase(s(A),[a,a,a,a,a]).
A = [2,2,1] ;
No

现在让我们试试是否可以重新排序。我们对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

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

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

再见

于 2012-10-07T11:59:09.843 回答
1

当 L 未被实例化时,该文法将用于文本生成。那么你根本不需要语法 \+ 。由于某些文本不再存在歧义问题。

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

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

t(2)     --> [a,a].                    % 3
t(1)     --> [a].                      % 4

每个不同的解析都有不同的解析树。并且使用短语/2 生成文本没有歧义。以下查询恰好给出了一个答案:

?- phrase(s([2,1]),L).
L = [a,a,a]
?- phrase(s([1,2]),L).
L = [a,a,a]
?- phrase(s([1,1,1]),L).
L = [a,a,a]

但是有一点重用的问题。假设我有一个带有 \+ 用于解析的 NL 语法。然后我不能用它来解析。由于 \+ 目标的实例化模式会有所不同,因此构造的语义会发生变化。

出路可能只是使用两种语法。一个用于解析,一个用于反解析。我猜解析和反解析是两种不同的认知能力。记得在学校里,有阅读练习和写作练习。计算机科学领域也是如此。

我认为在某些情况下也可以使用单个语法,并将 \+ 视为消歧的注释,在 unparse 期间删除或以不同方式处理。可以建立这样一种机制。但与解析相比,反解析的问题更深:辅助条件的双向性 ({}/1)、反解析期间的左递归等……

再见

于 2012-10-07T13:20:12.097 回答