如何在Prolog中根据指定id更新对应用户的体重数值?
问题原因
你当前代码失效的核心原因是存储逻辑和更新逻辑不匹配:你声明了动态谓词usersData/1用来存储所有用户的列表,但是没有将user/7声明为动态谓词,也没有单独存储每个user/7事实,retract自然找不到要删除的目标。以下提供两种可行的实现方案:
方案一:调整为单用户事实存储(更适合增删改查操作)
直接把每个用户作为独立的user/7事实存储,不需要用usersData包裹整个列表,修改量最小:
1. 声明动态谓词
% 声明user/7为动态谓词,支持运行时增删改 :- dynamic user/7.
2. 新增用户存储逻辑(替换原有buildUser逻辑即可)
% 构建并存储新用户 addUser(Id, Name, Age, Weight, Height, Plan, Training) :- % 避免重复插入同ID用户 \+ user(Id, _, _, _, _, _, _), assertz(user(Id, Name, Age, Weight, Height, Plan, Training)).
3. 优化体重更新逻辑
setWeight(Id, NewWeight) :- % 先查询对应用户的现有信息 user(Id, Name, Age, _, Height, Plan, Training), % 删除旧的用户事实 retract(user(Id, Name, Age, _, Height, Plan, Training)), % 插入更新后的用户事实 assertz(user(Id, Name, Age, NewWeight, Height, Plan, Training)). updateWeight(Data):- write('What\'s your id?: '), nl, readNumber(Id), nl, % 增加用户存在性校验 ( user(Id, _, _, _, _, _, _) -> write('What is your current weight?'), nl, readNumber(NewWeight), setWeight(Id, NewWeight) ; write('Error: User ID does not exist!'), nl ), begin(Data).
方案二:保留现有usersData存全量列表的设计
如果你需要保持所有用户存在同一个列表的存储设计,就修改更新逻辑操作列表内容即可:
% 原有存储定义不变 :- dynamic usersData/1. usersData([]). % 辅助谓词:遍历列表替换对应ID用户的体重 replaceUserWeight([], _, _, []). replaceUserWeight([user(Id, Name, Age, _, H, P, T)|Rest], Id, NewW, [user(Id, Name, Age, NewW, H, P, T)|Rest]) :- !. replaceUserWeight([U|Rest], Id, NewW, [U|NewRest]) :- replaceUserWeight(Rest, Id, NewW, NewRest). setWeight(Id, NewWeight) :- % 取出当前存储的全量用户列表 usersData(OldList), % 替换对应用户的体重 replaceUserWeight(OldList, Id, NewWeight, NewList), % 删除旧的列表事实,插入更新后的列表 retract(usersData(OldList)), assertz(usersData(NewList)).
内容的提问来源于stack exchange,提问作者Xiao
相关产品推荐
相关产品推荐

