这两个语句有什么区别:a) p(1),!; b) p(1):-!;

What is the difference between this two statements: a) p(1),!; b) p(1):-!;

这两个语句有什么区别:

a) p(1),!

b) p(1):-!

我遇到了这段代码:

p(1).
p(2):-!.
p(3).

如果我将其重写为:

p(1).
p(2),!.
p(3).

我相信您看到的是一个非常简单的例子,它使 p(2) :- !p(2), ! 之间的行为看起来相似或等价。看起来他们都在查询 p(2),如果成功匹配,则继续进行剪切并截断进一步回溯。但这并不是它们的工作方式。

表达式 p(2) :- !. 是一个谓词子句,它定义了一条规则,即 p(2) 为真,无需检查其他解决方案.当您进行 p(X) 形式的查询时,Prolog 将尝试找到匹配它的事实或规则头。在这种情况下,p(2) 是一个匹配并且 Prolog 遵循规则。作为具体示例,如果您有:

p(2).
p(2).

并查询:

| ?- p(X).

你得到:

| ?- p(X).

X = 2 ? ;

X = 2

(1 ms) yes
| ?-

然而,如果你有这些事实

p(2) :- !.
p(2).

然后你得到:

| ?- p(X).

X = 2

yes
| ?-

另一方面,表达式 p(2), !. 在句法上不能出现在 Prolog 中的 "top level" 处。换句话说,这不是合法的序言:

p(2), !.
p(2).

如果您尝试这样做,您将收到类似以下内容的错误:

error: user:1: native code procedure (',')/2 cannot be redefined (ignored)

Prolog 认为您正在尝试重新定义 , 运算符。那是因为表达式 p(2), !. 看起来像:

','(p(2), !).   % Create a definition for ','

确实 p(2) :- ! 在 Prolog 中被称为术语,':-'(p(2), !)p(2) 是子句的 head ) 它在顶层特别对待。但是,p(2), ! 在语法上需要成为子句的一部分,而不是在顶层。在这种情况下,术语 p(2) 不是 Prolog 试图匹配的子句的头部。相反,它是一个查询,它是另一个 Predicate 子句的一部分。例如:

% Define 'foo'
foo :- p(2), !.
foo.

如果我们查询:

| ?- foo.

yes
| ?-

你看成功了,因为cut,成功了一次就没有选择点了。另一方面,如果我们定义:

foo :- p(2).
foo.

然后查询行为不同:

| ?- foo.

true ? ;

yes

此处,foo 成功,并且由于缺少剪切和额外的 foo clause/fact,留下了一个选择点。我们告诉 Prolog 寻找更多的解决方案 (;),我们又得到一个,结果是 yes.

我说了这么多是为了表明对于两个不同的运算符来说,这些是非常不同的上下文:,:-