Prolog将一个变量与一个术语统一起来,然后忘记统一

Prolog将一个变量与一个术语统一起来,然后忘记统一,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), n

当两个列表相同时,除了索引
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
?这是轨迹的最后四个部分,在这里统一发生,然后被遗忘:

   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
我不怀疑有更好的方法交换两个元素(可能是递归的),但我想知道为什么会发生这种情况,以及如何修复它;我显然缺乏一些序言知识

谢谢

/2是所谓的“”。然后在循环之间撤消实例化

在SWI Prolog中,有/2,它修复了第一个查询的问题

...
numlist(0, Lim, Indices),
foreach((member(I, Indices), I \= I1, I \= I2),
       (nth0(I, List, V), nth0(I, NewList, V))).
测试:


在SWI Prolog中,有时更好的理解内置代码的方法是检查源代码。您可以看到foreach/2是一个相当复杂的谓词。。。在swipl提示符下,尝试
?-edit(foreach)。
,或从文档页面(圆圈)点击源链接。

forall/2
仅用于测试充分实例化的目标。很高兴看到
edit(foreach)的用法。
请继续提供这些提示。啊,谢谢!我以为我试过foreach,虽然我不明白其中的区别,但我想我没有试过用谓词的最终版本。同样感谢您的
编辑
提示。
\=/2
-->
=\=/2
?- swapped(0, 1, [1,2,3], L).
L = [2, 1, 3].