できるだけ単純にするために、現在チェックされている要素がリストかどうかのテストを追加できます。それが実際にリストである場合、その要素も逆にする必要があります。コードでは:
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 の回答をお読みください。