Recursion 在Clojure函数中获取堆栈溢出。
为什么在以下Clojure函数中出现堆栈溢出:Recursion 在Clojure函数中获取堆栈溢出。,recursion,clojure,Recursion,Clojure,为什么在以下Clojure函数中出现堆栈溢出: (defn length [xs] (if ,(not= xs nil) (println (+ 1 (length (rest xs)))) (println 0))) 切换到所有惰性seq后,rest将永远不会返回nil,只是一个空列表-尝试以下操作: (defn length [xs] (if (not (empty? xs)) (println (+ 1 (length (rest xs)
(defn length
[xs]
(if ,(not= xs nil)
(println (+ 1 (length (rest xs))))
(println 0)))
切换到所有惰性seq后,rest将永远不会返回nil,只是一个空列表-尝试以下操作:
(defn length
[xs]
(if (not (empty? xs))
(println (+ 1 (length (rest xs))))
(println 0)))
还是这个
(defn length
[xs]
(if ,(not= xs nil)
(println (+ 1 (length (next xs))))
(println 0)))
我认为这样做的惯用方法是对您的收藏调用
seq
<如果集合为空,则集合上的code>seq返回nil
(defn length [xs]
(if (seq xs)
(inc (length (rest xs)))
0))
这不是尾部递归(您没有使用recur
,在这里不能),因此这仍然会在非常大的集合上溢出堆栈
user> (println (length (range 1000000)))
;; stack overflow
单尾递归版本将是
(defn length [xs]
(loop [xs xs
acc 0]
(if (seq xs)
(recur (rest xs) (inc acc))
acc)))
user> (println (length (range 1000000)))
1000000
即使是对于大型集合,这也不会溢出堆栈,但仍然很慢。许多Clojure集合实现了
Counted
接口,内置的count
函数以恒定时间返回这些集合的长度。您不会谈论StackOverflow上的堆栈溢出。Lol不知道clojure,但当xs只有1个元素时,“rest xs”会返回nil吗?或者它会返回一个空的list/string/任何不是nil的东西吗?我假设堆栈只是溢出了预期的结果。Clojure不会自动优化尾部调用(虽然这不是尾部调用,但可以简单地重写为尾部调用)。我也很难相信这是在函数式语言中实现长度函数的最佳方法,在我看来,它的性能非常差。