prologでreverse

つかれた。

reverse(X,Y):-rev(X,[],Y).
rev([X|Xs],Z,Y):-rev(Xs,[X|Z],Y).
rev([],X,X).

答えをYに積んでいくパターン

[trace]  ?- reverse([1,2,3,4],X).
   Call: (7) reverse([1, 2, 3, 4], _G348) ? creep
   Call: (8) rev([1, 2, 3, 4], [], _G348) ? creep
   Call: (9) rev([2, 3, 4], [1], _G348) ? creep
   Call: (10) rev([3, 4], [2, 1], _G348) ? creep
   Call: (11) rev([4], [3, 2, 1], _G348) ? creep
   Call: (12) rev([], [4, 3, 2, 1], _G348) ? creep
   Exit: (12) rev([], [4, 3, 2, 1], [4, 3, 2, 1]) ? creep
   Exit: (11) rev([4], [3, 2, 1], [4, 3, 2, 1]) ? creep
   Exit: (10) rev([3, 4], [2, 1], [4, 3, 2, 1]) ? creep
   Exit: (9) rev([2, 3, 4], [1], [4, 3, 2, 1]) ? creep
   Exit: (8) rev([1, 2, 3, 4], [], [4, 3, 2, 1]) ? creep
   Exit: (7) reverse([1, 2, 3, 4], [4, 3, 2, 1]) ? creep
X = [4, 3, 2, 1].

このパターンを忘れるなかれ。

a([X|Xs],Z):-a(Xs,[X|Z]).
a([],_).
[trace]  ?- a([1,2,3],[]).
   Call: (7) a([1, 2, 3], []) ? creep
   Call: (8) a([2, 3], [1]) ? creep
   Call: (9) a([3], [2, 1]) ? creep
   Call: (10) a([], [3, 2, 1]) ? creep
   Exit: (10) a([], [3, 2, 1]) ? creep
   Exit: (9) a([3], [2, 1]) ? creep
   Exit: (8) a([2, 3], [1]) ? creep
   Exit: (7) a([1, 2, 3], []) ? creep
true.

traceを使わずにwriteでprintするデバッグもある。

reverse(X,Y):-rev(X,[],Y).
rev([X|Xs],Z,Y):-write([X|Xs]),write(','),writeln(Z),rev(Xs,[X|Z],Y).
rev([],X,X).
?- reverse([1,2,3],X).
[1, 2, 3],[]
[2, 3],[1]
[3],[2, 1]
X = [3, 2, 1].

formatでもいい。

reverse(X,Y):-rev(X,[],Y).
rev([X|Xs],Z,Y):-format('~p,\t~p\n',[[X|Xs],Z]),rev(Xs,[X|Z],Y).
rev([],X,X).