为什么我需要复制我的 Prolog 谓词才能使我的程序运行?

Why do I need to duplicate my Prolog predicates in order to make my program work?

我正在使用 SICStus Prolog 4.0.8 编写一个程序来解析英文句子和 returns 句法树,以及 yes/no 根据编程的语法。这是一个例子(句子是 Larry 和 Carol meet their older neighbors Paul and Lillian):

s(s(N, V)) --> np(N), vp(V).
np(np1(N1, C, N2)) --> pn(N1), conj(C), pn(N2).
np(np2(D, A, N)) --> det(D), adj(A), cn(N).
app(app(N1, N2)) --> np2(N1), np1(N2).
vp(vp1(V, A)) --> tv(V), app(A).

如果我 运行 这样的代码,它会抱怨 np2/3 没有定义,但是如果我把数字放在括号之前,它会抱怨 np/3 没有定义.我唯一的解决方案是将两个谓词都放入,如下所示:

s(s(N, V)) --> np(N), vp(V).
np(np1(N1, C, N2)) --> pn(N1), conj(C), pn(N2).
np(np2(D, A, N)) --> det(D), adj(A), cn(N).
app(app(N1, N2)) --> np2(N1), np1(N2).
vp(vp1(V, A)) --> tv(V), app(A).
np1(np1(N1, C, N2)) --> pn(N1), conj(C), pn(N2).
np2(np2(D, A, N)) --> det(D), adj(A), cn(N).
vp1(vp1(V, A)) --> tv(V), app(A).

然后编译执行成功。这种行为的原因是什么?

在您代码的第一个版本中,子句

np(np1(N1, C, N2)) --> pn(N1), conj(C), pn(N2).

定义谓词np/3(并调用谓词pn/3)。但是,子句

app(app(N1, N2)) --> np2(N1), np1(N2).

调用未定义的谓词 np2/3np1/3。这就是运行时错误的原因。

在您代码的第二个版本中,还定义了谓词np2/3np1/3,因此没有错误。

有什么问题? 我认为你混淆了 np/3pn/3(它们是 谓词 np1/3np2/3 表示语法树节点)。


np( np1(N1, C, N2) ) --> pn(N1), conj(C), pn(N2).
^    ^                   ^
|    |                   |
|    |                   +--- predicate being called (must be defined)
|    |
|    +----------------------- term representing a syntax tree node (this is not a predicate) 
|
+---------------------------- predicate being defined