Prolog游戏库存谓词inv/2查询异常求助:inv(2,R)返回false
问题分析与解决方案
你的inv/2谓词在查询inv(2, R)时返回false,核心问题出在\+ member(X, Rest)这一行。当Rest是未实例化的变量时,member(X, Rest)会直接成功——Prolog中未绑定的变量可以与任何项匹配,相当于默认假设Rest包含X,取反后\+ member(X, Rest)就会失败,导致递归分支无法执行。最终只有inv(0, [])能匹配,但你的查询中N=2,所以整体返回false。
修复方案一:先收集所有物品再筛选
先定义一个获取所有已拥有物品的谓词,再从中选取N个不重复的元素:
:- dynamic have/1. all_have(Items) :- findall(Item, have(Item), Items). inv(N, R) :- all_have(AllItems), length(R, N), subset(R, AllItems), % 确保R中无重复元素 sort(R, SortedR), length(SortedR, N).
修复方案二:调整递归逻辑顺序
修改递归执行顺序,先生成Rest再检查X是否重复,此时Rest已被实例化,\+ member(X, Rest)能正确工作:
:- dynamic have/1. inv(0, []). inv(N, [X | Rest]) :- N > 0, N1 is N - 1, inv(N1, Rest), have(X), \+ member(X, Rest).
注:这个版本会生成元素顺序不同的重复结果(比如[classic_gun, medkit]和[medkit, classic_gun]会被视为两个独立结果),如果需要去重,可以在查询后添加排序约束。
内容的提问来源于stack exchange,提问作者Andrey Morozov
相关产品推荐
相关产品推荐

