我正在尝试递归地反转列表,但是我得到了Can only recur from tail position
运行时。这到底意味着什么?如何改进我的代码才能使其正常工作?
(defn recursive-reverse [coll]
(loop [coll coll]
(if (< (count coll) 2) '(coll)
(conj (first coll) (recur (rest coll)))
)))
EDIT
Oscar 解的输出。它适用于列表但不适用于向量?
user=> (= (recursive-reverse [1 2 3 4 5]) (recursive-reverse '(1 2 3 4 5)))
false
user=> (= '(1 2 3 4 5) [1 2 3 4 5])
true
user=> (recursive-reverse [1 2 3 4 5])
[1 2 3 4 5]
user=> (recursive-reverse '(1 2 3 4 5))
(5 4 3 2 1)
错误Can only recur from tail position
意味着你没有打电话recur
作为函数递归部分的最后一个表达式 - 事实上,在您的代码中conj
是最后一个表达式。
一些使您的代码正常工作的改进:
- 询问集合是否为空作为基本情况,而不是比较其长度是否小于二
-
conj
收到一个收藏为其第一个参数,而不是元素
- 使用它是一个更好的主意
cons
代替conj
(根据集合的具体类型,在不同的位置添加新元素文档 http://clojuredocs.org/clojure_core/clojure.core/conj)。这样,如果输入集合是列表或向量,则返回的集合将被反转(尽管返回集合的类型始终是clojure.lang.Cons
,无论输入集合的类型是什么)
- 意识到
'(coll)
是一个包含单个元素的列表(符号coll
) and not实际集合
- 为了正确反转列表,您需要迭代输入列表并将每个元素附加到输出列表的开头;为此使用累加器参数
- 用于利用尾递归调用
recur
位于函数的尾部位置;这样,每次递归调用都会占用恒定的空间,并且堆栈不会无限增长
我相信这就是您的目标:
(defn recursive-reverse [coll]
(loop [coll coll
acc (empty coll)]
(if (empty? coll)
acc
(recur (rest coll) (cons (first coll) acc)))))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)