0

p(integer),q(integer),r(integer)考虑以流模型(o)和谓词为谓词的 Prolog s

p(1). q(1). r(1).
p(2). q(2). r(2).
s:-!,p(X),q(Y),r(Z),write(X,Y,Z),nl.

给出以下目标的结果:s。证明答案。

结果是 111,112,121,122,211,212,221,222。我已经看到如果它位于子句的开头,则剪切无效。这是真的?

4

2 回答 2

1

如果它位于子句的开头,则剪切无效。”

不完全是。这将取决于这样的谓词是否有其他子句。

而且:

  • 谓词write是一元的,不能用三个参数调用。
  • 最好在每个谓词的定义中对子句进行分组。

正确的程序是:

p(1). p(2).
q(1). q(2).
r(1). r(2).

s :- !, p(X), q(Y), r(Z), writeln(X-Y-Z).

确实,对于这个程序,cut没有任何效果。但是,请考虑以下新版本的程序。

p(1). p(2).
q(1). q(2).
r(1). r(2).

s :- !, p(X), q(Y), r(Z), writeln(X-Y-Z).
s :- writeln(here).                       % <= this clause will not be executed!

在这种情况下,cut谓词的第一个子句中的s将阻止第二个子句的执行。

于 2021-01-09T14:33:01.690 回答
0

“如果它位于子句的开头,则剪切无效”

这不是真的(好吧,它就在这里,但是是偶然的)。

切的意思是“不要回溯到这里的左边,而是使谓词失败”。

因此,如果在当前子句之后(在词法上)有附加子句,这意味着“承诺谓词的当前子句,忽略任何进一步的子句”。

您也可以将其读作“守卫行动”分隔符,执行“第一个守卫获胜”逻辑,其中相应的守卫行动(并且只有那个)在守卫成功时运行:

head1 :- guard1,!,action1.
head2 :- guard2,!,action2.
head3 :- guard3,!,action3.
head4 :- else_action.

对于s/0,在 之前实际上有一个空守卫!,因此不会发生守卫测试,只是对当前子句的承诺。但是只有一个子句 for s/0,所以提交什么也不做。

于 2021-01-09T14:34:09.047 回答