Вы неправильно поняли запись [H|T]
, трассировка по примеру reverse(L, [a, b])
покажет ее.
Первое объединение:
rule: myReverse([L|H],[H|T]) :- myReverse(L,T).
unified: myReverse([L|a], [a|[b]]) :- myReverse(L, [b]).
На данный момент a
- это отдельный атом, а не список, T in [H|T]
должен быть списком, чтобы список был полным. [a, b, c]
является синтаксическим сахаром для .(a, .(b, .(c, [])))
.
Ваше второе и третье объединения:
second: myReverse([b], [b]).
going back: myReverse([[b]|a], [a|[b]]) :- myReverse([b], [b]).
which outputs as: myReverse([[b]|a], [a, b]).
Ваш вывод [[b]|a]
не является полным списком, поскольку a
был атомом, а не списком, поэтому он не выводится как [[b], a]
.
Чтобы не использовать аккумулятор, вам нужно добавлять элементы в список при выходе из рекурсии и возвращаться назад через стековые фреймы, учитывая при обработке списка или атома:
myReverse([], []). % base case
myReverse([Head|Tail], Reversed) :-
myReverse(Tail, TailReversed), % recursive call
add_to_tail(Head, TailReversed, Reversed). % Put Head onto the end
add_to_tail(X, [],[X]). % base case
add_to_tail(X, [H|T], [H|Out]) :-
add_to_tail(X, T, Out). % recursive call, work done on exit
Более эффективно использовать аккумулятор. Желаем удачи в изучении пролога.