无直接访问事实名称时,如何在Prolog中撤回动态事实?
如何在Prolog中通过动态名称撤回动态事实?
我想撤回Prolog中的动态事实,但无法直接获取该事实的名称。之前我通过以下代码调用这类事实:
facts.pl 文件内容:
:- dynamic fact/2. fact(a, b). fact(b, e). fact(a, c). fact(e, d). fact(c, d). fact(d, f). fact(d, g).
solution.pl 文件内容:
someProcedure(StructureName) :- call(StructureName, a, X).
我尝试用以下代码撤回事实,但报错了:
deleteProcedure(StructName, A, B) :- retract(call(StructName, A, B)).
报错信息:
ERROR: retract/1: No permission to modify static procedure `call/3' ERROR: Defined at /usr/lib/swi-prolog/boot/init.pl:217
你不能直接把call/3放进retract/1里,因为retract需要的是目标结构本身,而非call包装后的形式。以下是两种正确的实现方式:
方法1:直接使用复合项语法
deleteProcedure(StructName, A, B) :- retract(StructName(A, B)).
方法2:用=../2(univ操作符)构造事实结构
如果需要更灵活的动态构造,可以用这个操作符把谓词名和参数组合成事实项:
deleteProcedure(StructName, A, B) :- Fact =.. [StructName, A, B], % 生成如 fact(a,b) 这样的结构 retract(Fact).
错误原因说明
你之前的代码试图撤回call/3这个内置静态谓词的子句,但call/3是系统自带的静态过程,不允许修改,因此触发了权限错误。正确的思路是直接操作目标谓词的结构,而非通过call间接包装。
测试示例
调用deleteProcedure(fact, a, b)后,再查询fact(a,b)会返回false,说明该动态事实已成功从内存中撤回。
内容的提问来源于stack exchange,提问作者Temax
相关产品推荐
相关产品推荐

