Prolog不使用bagof/findall等内置谓词能否收集谓词结果到列表
问题解答
可以实现,核心思路是借助Prolog的回溯特性+动态谓词操作存储中间结果,不需要用到bagof/3、findall/3这类集合收集类内置谓词。
注意:纯声明式的无副作用Prolog逻辑无法完成该需求,因为回溯过程会撤销所有变量绑定,没有跨回溯的状态存储能力,需要用到
asserta/1、retract/1这类动态谓词操作的内置谓词,这类不属于你禁止使用的集合查询类内置谓词范围。
实现步骤与示例代码
- 首先定义动态临时谓词,用于存储匹配到的B值
% 声明动态临时存储谓词 :- dynamic temp_b/1.
- 定义收集主逻辑
collect_all_B(A, BList) :- % 清空历史临时数据,避免干扰 retractall(temp_b(_)), % 回溯匹配所有符合条件的B,存入临时谓词 ( a(A, B), assertz(temp_b(B)), % 用assertz保持结果和a谓词定义顺序一致,用asserta则是倒序 fail % 强制回溯,遍历所有解 ; % 所有解匹配完成后,把临时存储转成结果列表 collect_temp(BList) ). % 辅助谓词:把临时存储的所有值转成列表 collect_temp([]) :- \+ temp_b(_). collect_temp([B|Rest]) :- retract(temp_b(B)), collect_temp(Rest).
测试示例
假设你定义的a/2谓词如下:
a(1, x). a(1, y). a(1, z). a(2, m).
调用collect_all_B(1, Result),得到的Result值为[x, y, z],完全符合需求。
注意事项
- 该方法在单线程Prolog环境下稳定可用,多线程环境下需要给临时谓词加线程隔离标记,避免不同查询的临时数据互相干扰
- 如果你要求完全不使用任何副作用类内置谓词,那么无法实现该需求,这是Prolog的逻辑执行模型决定的。
内容的提问来源于stack exchange,提问作者Eason51
相关产品推荐
相关产品推荐

