Prolog 制作反向列表

Prolog 制作反向列表,prolog,Prolog,我有以下代码。试图制作一个反向列表。但它不起作用 reverse([],[H|T]). reverse([H|T],Z) :- reverse(T,[H|Z]). 我在prolog中运行这个,我得到了: 1 ?- trace, reverse([1,2,3],X). Call: (7) reverse([1, 2, 3], _G396) ? creep Call: (8) reverse([2, 3], [1|_G396]) ? creep Call: (9) reverse

我有以下代码。试图制作一个反向列表。但它不起作用

reverse([],[H|T]).
reverse([H|T],Z) :- reverse(T,[H|Z]).
我在prolog中运行这个,我得到了:

1 ?- trace, reverse([1,2,3],X).
   Call: (7) reverse([1, 2, 3], _G396) ? creep
   Call: (8) reverse([2, 3], [1|_G396]) ? creep
   Call: (9) reverse([3], [2, 1|_G396]) ? creep
   Call: (10) reverse([], [3, 2, 1|_G396]) ? creep
   Exit: (10) reverse([], [3, 2, 1|_G396]) ? creep
   Exit: (9) reverse([3], [2, 1|_G396]) ? creep
   Exit: (8) reverse([2, 3], [1|_G396]) ? creep
   Exit: (7) reverse([1, 2, 3], _G396) ? creep
true.

这应该给我[3,2,1],而不是[1,2,3]。这里出了什么问题???

当列表为空时,其反面为空。 所以

在另一种情况下,将列表的第一个元素附加到列表其余部分的末尾。因此:

reverse([H|T],Z) :-
    reverse(T,Z1),
    append(Z1, [H], Z).

你几乎把它做好了。您需要的是一个“累加器”,它收集到目前为止的结果,并在递归结束时将其传递给返回变量:

reverse([],Z,Z).
reverse([H|T],Z,Acc) :- reverse(T,Z,[H|Acc]).
否则,当函数从递归调用返回时,会忘记反转列表。调用
reverse/3
时,需要用空列表实例化累加器:

?- reverse([1,2,3],X,[]).

如果您进行跟踪,您将看到第二个参数在原始列表为空之前不会被实例化。

@scarface您确定吗?如果它没有做任何事情,你应该完全忽略它,看看会发生什么。@scarface顺便说一句,这是一个使用实现的
reverse
的教科书实现。例如,我也看到了。事实上,我看到它需要在那里。我想知道如何解释当反向([],z,z)被调用时,累加器的值被保存在中间,即使递归超出了深度。我不明白为什么Acc在退出递归深度时会一点一点地消失,而Z在最后一次调用中被“赋值”,然后即使我们退出递归深度,它也会保持赋值。还有,我怎么能想象第一行是什么呢?“我真的不明白。”scarface如前所述,这是教科书上的东西,所以拿一本教科书来读。例如,我会推荐斯特林和夏皮罗的《序言的艺术》,尽管我怀疑这可能也会在像“现在就学习序言!”这样的教科书中在网上得到解释。或者,只需问另一个问题:你可以将这个问题与答案联系起来,解释你不清楚的地方,并提出更具体的问题!
?- reverse([1,2,3],X,[]).