如何在单个assert/1语句中断言多个Prolog事实或规则?
在Prolog中单次调用断言多个事实/规则的方法
为什么assert((bar(a),bar(b),bar(c)))无效
assert/1的参数要求是单个子句(事实或规则),这里的逗号是逻辑合取运算符,它会把(bar(a),bar(b),bar(c))当作一个整体的复合事实存入知识库,而不是拆分成三个独立的bar/1事实,所以达不到预期效果。
实现单次调用断言多个子句的方法
以下是几种实用方案,适用于事实和规则:
使用
maplist/2遍历列表(SWI-Prolog等主流实现支持)
把要断言的所有子句放到列表里,通过maplist/2逐个调用assertz/1(或asserta/1,控制插入位置):?- maplist(assertz, [foo(a), foo(b), foo(c), (p(X) :- q(X)), (r(Y) :- s(Y))]).这个写法只需要一次顶级调用,内部自动遍历列表完成所有断言。
用
forall/2配合成员遍历
通过forall/2实现循环断言,同样是单次调用:?- forall(member(Clause, [foo(a), foo(b), foo(c)]), assertz(Clause)).自定义断言多子句的谓词
如果你的Prolog环境不支持maplist/2,可以自己写一个递归谓词处理列表:assert_multiple([]). assert_multiple([Clause|Rest]) :- assertz(Clause), assert_multiple(Rest).调用时直接传入子句列表:
?- assert_multiple([foo(a), foo(b), foo(c), (p(X) :- q(X))]).
注意事项
assertz/1会把新子句添加到知识库末尾,asserta/1会添加到开头,根据需求选择。- 不同Prolog实现的内置谓词可能有差异,比如有些轻量实现可能没有
maplist/2,此时自定义谓词是通用方案。
内容的提问来源于stack exchange,提问作者Elliot Mummel
相关产品推荐
相关产品推荐

