为了让事情尽可能简单,我们可以添加一个测试,如果当前被检查的元素是一个列表或不是一个列表。如果它确实是一个列表,那么它的元素也应该颠倒过来。所以在代码中:
my_reverse(L,R) :- rev(L,[],R).
rev([],A,A).
rev([H|T],A,R) :-
( is_list(H) -> % If H is a list
rev(H,[],X), % then reverse H as well
rev(T,[X|A],R)
;
rev(T,[H|A],R)
).
另外,这并不重要,只是为了避免混淆,请注意我是如何分别使用A
和和的。在您的代码中,它们当前被交换,这 - 对我个人而言 - 可能有点令人困惑,尤其是当谓词变得更长和更复杂时。R
Accumulator
Result
无论如何,让我们看看您提供的查询:
?- my_reverse([[0,1],2,3],R).
R = [3, 2, [1, 0]].
?- my_reverse([1,2,[3,4,5,[6,7],8],[9,10],11,12],R).
R = [12, 11, [10, 9], [8, [7, 6], 5, 4, 3], 2, 1].
以及一些一般性查询:
?- my_reverse(L,R).
L = R, R = [] ;
L = R, R = [_G2437] ;
L = [_G2437, _G2443],
R = [_G2443, _G2437] ;
L = [_G2437, _G2443, _G2449],
R = [_G2449, _G2443, _G2437] ;
L = [_G2437, _G2443, _G2449, _G2455],
R = [_G2455, _G2449, _G2443, _G2437]
...
?- my_reverse([[X,Y]|T],R), member(a,T), length(X,2).
X = [_G2588, _G2591],
T = [a],
R = [a, [Y, [_G2588, _G2591]]]
;
X = [_G2594, _G2597],
T = [a, _G2588],
R = [_G2588, a, [Y, [_G2594, _G2597]]]
;
X = [_G2594, _G2597],
T = [_G2582, a],
R = [a, _G2582, [Y, [_G2594, _G2597]]]
...
但是请注意,使用此谓词,在找到查询的第一个答案后不会发生终止:
?- my_reverse(X,[X]).
X = [X] ;
...
但由于这不是 OP 问题中的要求/要求,我认为这没问题。
编辑:
请阅读@mat 的答案作为此问题的后续行动。