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。我已经看到如果它位于子句的开头,则剪切无效。这是真的?
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。我已经看到如果它位于子句的开头,则剪切无效。这是真的?
如果它位于子句的开头,则剪切无效。”
不完全是。这将取决于这样的谓词是否有其他子句。
而且:
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
将阻止第二个子句的执行。
“如果它位于子句的开头,则剪切无效”
这不是真的(好吧,它就在这里,但是是偶然的)。
切的意思是“不要回溯到这里的左边,而是使谓词失败”。
因此,如果在当前子句之后(在词法上)有附加子句,这意味着“承诺谓词的当前子句,忽略任何进一步的子句”。
您也可以将其读作“守卫行动”分隔符,执行“第一个守卫获胜”逻辑,其中相应的守卫行动(并且只有那个)在守卫成功时运行:
head1 :- guard1,!,action1.
head2 :- guard2,!,action2.
head3 :- guard3,!,action3.
head4 :- else_action.
对于s/0
,在 之前实际上有一个空守卫!
,因此不会发生守卫测试,只是对当前子句的承诺。但是只有一个子句 for s/0
,所以提交什么也不做。