prolog - Prolog 将变量与术语统一然后忘记统一
问题描述
我编写了以下谓词,用于识别两个列表何时相同,除了索引处的两个元素I1
并被I2
交换:
swapped(I1, I2, List, NewList) :-
% The lists are the same length and the two indices are swapped.
same_length(List, NewList),
nth0(I1, List, V1), nth0(I2, List, V2),
nth0(I1, NewList, V2), nth0(I2, NewList, V1),
% All the other indices remain the same.
proper_length(List, Length), Lim is Length - 1,
numlist(0, Lim, Indices),
forall((member(I, Indices), I \= I1, I \= I2),
(nth0(I, List, V), nth0(I, NewList, V))).
以下swipl
输出演示了我的问题:
?- swapped(0, 1, [1,2,3], L).
L = [2, 1, _G5035].
?- swapped(0, 1, [1,2,3], [2,1,3]).
true.
?- swapped(0, 1, [1,2,3], [2,1,4]).
false.
3
既然它可以识别出这3
是唯一正确的术语,为什么它会返回第三个元素的变量而不是 just ?这些是统一发生然后被遗忘的痕迹的最后四个部分:
Call: (10) lists:nth0(2, [2, 1, _G6121], 3) ? creep
Exit: (10) lists:nth0(2, [2, 1, 3], 3) ? creep
^ Exit: (8) forall(user: (member(_G6145, [0, 1, 2]), _G6145\=0, _G6145\=1), user: (nth0(_G6145, [1, 2, 3], _G6162), nth0(_G6145, [2, 1, _G6121], _G6162))) ? creep
Exit: (7) swapped(0, 1, [1, 2, 3], [2, 1, _G6121]) ? creep
我不怀疑有更好的方法来交换两个元素(也许是递归的),但我想知道为什么会发生这种情况以及如何解决它;我显然缺乏一些 Prolog 知识。
谢谢!
解决方案
forall /2 是所谓的“故障驱动循环”。然后在循环之间撤消实例化。
在 SWI-Prolog 中,有foreach /2,它解决了您的第一个查询的问题。
...
numlist(0, Lim, Indices),
foreach((member(I, Indices), I \= I1, I \= I2),
(nth0(I, List, V), nth0(I, NewList, V))).
测试:
?- swapped(0, 1, [1,2,3], L).
L = [2, 1, 3].
在 SWI-Prolog 中,有时了解内置函数的更好方法是检查源代码。您可以看到 foreach/2 是一个相当复杂的谓词...从 swipl 提示符、try或从文档页面(带圆圈的:-)?- edit(foreach).
访问源链接。
推荐阅读
- amazon-web-services - 区分 Shell 变量和 Cloudformation 模板参数
- phpstan - 怎么说phpstan那个类被孩子代替了
- sql - 使用基于 id 的条件获取最旧的记录
- c - 调用退出函数后,对 printf 的调用不显示在反汇编中
- python - 如何从需要 conda 包的文本文件中保存的 URL 下载文件?
- asp.net-mvc - 在 MVC 中没有登录表单的 Active Directory 身份验证
- django - 从 Django 中的自定义 html 表单添加和更新帖子
- bash - 仅在非交互模式下验证失败
- c# - C#错误并非所有代码路径都返回一个值,当只做查询时返回值就好了
- r - 在 r ggplot 的热图中裁剪地理边界