说我有这样的功能:
user=> (def m {10 5, 5 2, 2 1})
#'user/m
user=> (defn hierarchy [x] (when x (cons x (hierarchy (get m x)))))
#'user/hierarchy
user=> (hierarchy 10)
(10 5 2 1)
user=>
显然这里很好,因为堆栈深度会很小。但对于这种一般类型的问题,我正在构建一个我想要返回的列表,递归调用总是在一个cons调用中结束。我如何将其转换为尾递归,以便我可以使用recur而不占用堆栈空间?
答案 0 :(得分:3)
阅读累加器。
在Clojure中,可以使用lazy-seq
解决此特定问题。 lazy-seq
推迟计算,因此堆栈溢出(通常)不是问题。
(defn hierarchy
[x]
(when x
(lazy-seq
(cons x (hierarchy (get m x))))))
答案 1 :(得分:3)
您可以在不使用递归的情况下优雅地解决此问题:
(defn hierarchy [x]
(take-while identity (iterate m x)))
答案 2 :(得分:2)
第一个变种
(defn hierarchy* [res x]
(if-not x
res
(recur (conj res x) (get m x))))
(defn hierarchy [x]
(hierarchy* [] x))
第二
(defn hierarchy [x]
(loop [res []
next-x x]
(if-not next-x
res
(recur (conj res next-x) (get m next-x)))))
答案 3 :(得分:1)
添加lazy-seq
:
(defn hierarchy [x] (when x (cons x (lazy-seq (hierarchy (get m x))))))