问题在于您使用的是==/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),原因与上述完全相同。
最后,正如@Boris 指出的那样,在 Prolog 中,统一谓词将适用于整个列表。在这种情况下,这就足够了:
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。