我想编写一个函数,如果两个列表完全相同(元素的顺序很重要),则返回true。
我试过这种方式:
same([ ], [ ]).
same([H1|R1], [H2|R2]):-
H1 == H2,
same(R1, R2).
当两个列表相同时返回true,如果我有
,我也期望?- same(X, [1, 2, 3]).
我希望它返回
X = [1, 2, 3].
但如果输入是这样的话,它就不起作用。以下是我得到的一些示例输出:
?- same([1, 2], [1, 2]).
true.
?- same([2, 1], [1, 2]).
false.
?- same(X, [1, 2, 3]).
false.
?- same([1, 2, 3], [1, 2, X]).
false.
如何解决?
答案 0 :(得分:3)
问题是你正在使用==/2
(检查两个项是否实例化相同)而不是=/2
(检查两个项是统一的还是统一的)。只需改为统一:
same([], []).
same([H1|R1], [H2|R2]):-
H1 = H2,
same(R1, R2).
然后这将有您正在寻找的行为:
| ?- same(X, [1, 2, 3]).
X = [1,2,3] ? a
no
| ?- same([1, 2], [1, 2]).
(1 ms) yes
| ?- same([2, 1], [1, 2]).
no
| ?- same([1, 2, 3], [1, 2, X]).
X = 3
(1 ms) yes
| ?- same([A,B,C], L).
L = [A,B,C]
yes
% In this last example, A, B, and C are variables. So it says L is [A,B,C],
% whatever A, B, and C are.
如果您在Prolog中查询X == 3
,并且X
未绑定到值3
,或者它只是未绑定,则会失败。如果X
未绑定且您查询X = 3
,则Prolog会将X
(绑定)与3
统一起来,并且会成功。
有关=/2
和==/2
之间差异的详情,请参阅What is the difference between == and = in Prolog?
您还可以使用maplist
获得一个漂亮,紧凑的解决方案。 maplist
非常便于迭代列表:
same(L1, L2) :- maplist(=, L1, L2).
此处,统一(=/2
)仍然使用与上述完全相同的原因。
same(L1, L2) :- L1 = L2.
或等效地:
same(L, L). % Would unify L1 and L2 queried as same(L1, L2)
如果列表相同,这将成功,或者尝试通过依次统一每个元素来统一它们。
| ?- same([1,2,X], [1,2,3]). % Or just [1,2,X] = [1,2,3]
X = 3
yes
| ?- same([1,2,X], [1,2,3,4]). % Or just [1,2,X] = [1,2,3,4]
no
先前更精细的方法被认为是列表处理中的练习以用于说明。但是,用于比较和/或统一列表的最简单和最正确的方法是L1 = L2
。