prolog 两个列表完全一样

Mic*_*icM 1 list prolog

如果两个列表完全相同(元素的顺序很重要),我想编写一个返回 true 的函数。

我是这样试的:

same([ ], [ ]).   
same([H1|R1], [H2|R2]):-
    H1 == H2,
    same(R1, R2).
Run Code Online (Sandbox Code Playgroud)

当两个列表相同时它返回真,我也希望如果我有

?- same(X, [1, 2, 3]).
Run Code Online (Sandbox Code Playgroud)

我想要它回来

X = [1, 2, 3].
Run Code Online (Sandbox Code Playgroud)

但是这样输入就不行了。以下是我得到的一些示例输出:

?- 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.
Run Code Online (Sandbox Code Playgroud)

如何解决?

lur*_*ker 5

问题在于您正在使用==/2(检查两个项目是否实例化相同)而不是=/2(检查两个项目是否统一或统一)。只需更改为统一:

same([], []).

same([H1|R1], [H2|R2]):-
    H1 = H2,
    same(R1, R2).
Run Code Online (Sandbox Code Playgroud)

然后这将具有您正在寻找的行为:

| ?- 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.
Run Code Online (Sandbox Code Playgroud)

如果X == 3在 Prolog 中查询,并且X未绑定到 value 3,或者只是未绑定,则会失败。如果X未绑定并且您查询 ,X = 3则 Prolog 将统一X(绑定)与3并成功。

有关=/2和之间区别的更多信息==/2,请参阅Prolog 中 == 和 = 之间的区别是什么?

您也可以使用maplist一个漂亮的、紧凑的解决方案。maplist对于遍历列表非常方便:

same(L1, L2) :- maplist(=, L1, L2).
Run Code Online (Sandbox Code Playgroud)

这里,=/2出于与上述完全相同的原因,仍然使用统一 ( )。


最后,正如@Boris 指出的那样,在 Prolog 中,统一谓词将适用于整个列表。在这种情况下,这就足够了:

same(L1, L2) :- L1 = L2.
Run Code Online (Sandbox Code Playgroud)

或等效地:

same(L, L).  % Would unify L1 and L2 queried as same(L1, L2)
Run Code Online (Sandbox Code Playgroud)

如果列表相同,这将成功,或者将尝试通过依次统一每个元素来统一它们。

| ?- 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
Run Code Online (Sandbox Code Playgroud)

先前更精细的方法被认为是列表处理中的练习以供说明。但是比较和/或统一列表的最简单和最正确的方法是L1 = L2.