这对我来说有些事情retract/1
没有意义。
根据 ISO/IEC 13211-1:1995:
8.9.3 收回/1
8.9.3.1 说明
retract(Clause)
如果数据库包含至少一个带有与Clause
结合的子句的动态过程,则为真Head :- Body
。在程序
retract(Clause)
上,执行如下:a) 如果
Clause
与 结合':-'(Head, Body)
,则进行到 8.9.3.1 c,b) Else
Head
与Clause
和true
结合Body
,c) 依次搜索数据库中的每个动态用户定义过程,并创建一个包含所有术语的列表L
clause(H, B)
,使得 1) 数据库包含一个子句,其头部可以转换为术语H
(7.6.3),其主体可以被转换为一个项B
(7.6.4),并且 2)H
与 一致Head
,并且 3)B
与 一致Body
。d) 如果找到非空列表,则进行到 8.9.3.1 f,
e) 否则目标失败。
f) 选择列表L的第一个元素,从数据库中删除与其对应的子句,目标成功。
g) 如果列表L的所有元素都已被选择,则目标失败。
h) Else 选择列表L中尚未选择的第一个元素,如果存在,则从数据库中删除与其对应的子句,目标成功。
retract(Clause)
是可以重新执行的。回溯时,继续 8.9.3.1 g。[...]
“如果它存在”?重新执行后怎么可能不存在了?
数据库更新语义表明“它”始终存在:
7.5.4 逻辑数据库更新
由于执行目标而发生的数据库中的任何更改(例如,当子目标的激活器是对
assertz/1
or的调用时retract/1
)应仅影响随后开始执行的激活。此更改不应影响当前正在执行的任何激活。注意——因此数据库在目标执行期间被冻结,并且定义谓词的子句列表在其执行时是固定的(见 7.7.7 e)。
下面,我尝试在重新执行之前使用retract(f(3))
to make 子句消失:f(3)
retract(f(X))
?- abolish(f/1), maplist(assertz,[f(1),f(2),f(3)])。 真的。% 设置完成 ?- 缩回(f(X)),(X = 2 -> 缩回(f(3));真)。 X = 1 ; X = 2 ; X = 3。% <----------------^^^^^^^^^^^^^
...但是,唉,我失败了:SICStus Prolog、GNU Prolog 和 SWI-Prolog 给出了相同的(以上)答案。
那么为什么在这种情况下使用“如果它存在”这个短语呢?对我来说这是多余的。和令人费解的......请帮助!