我正试图用clojure包围递归.我使用以下代码得到堆栈溢出错误,有人能发现问题吗?
(我知道这是低效的,但它严格用于学习目的)
user=> (defn addall
([] 0)
([& x]
(if (empty? x) 0)
(+ (first x) (addall (rest x)))))
user/addall
user=> (addall 1)
StackOverflowError clojure.lang.ArraySeq.next (ArraySeq.java:78)
Run Code Online (Sandbox Code Playgroud)
看起来你的括号是错误的 - 你if需要一个else表格.我怀疑你的意思是:
(defn addall
([] 0)
([& x]
(if (empty? x)
0 ;;; <=== no ')' after 0
(+ (first x) (addall (rest x)))))) ;;; <== extra ')' here
Run Code Online (Sandbox Code Playgroud)
但即使修复了这个问题,你的代码仍然是错误的:它假定它是用多个参数调用的(addall 1 2 3)- 但是通过传递自己的列表来重复 - (addall [2 3]).这导致它陷入一个没有任何进展的循环中,你可以通过添加一个print语句来观察:
(defn addall
([] 0)
([& x]
(print (str "new x: " x "\n"))
(if (empty? x)
0 ;;; <=== no ')' after 0
(+ (first x) (addall (rest x))))))
Run Code Online (Sandbox Code Playgroud)
这实际上在我的电脑上产生了一个段错误!
此外,它有两个基本情况.我建议这样做:
(defn addall
[xs]
(if (empty? xs)
0
(+ (first xs)
(addall (rest xs)))))
Run Code Online (Sandbox Code Playgroud)
用向量调用:
(addall [1 2 3])
Run Code Online (Sandbox Code Playgroud)
或者,如果要使用可变参数函数,还需要apply:
(defn addall
[& x]
(print (str "new x: " x "\n"))
(if (empty? x)
0
(+ (first x)
(apply addall (rest x))))) ;;; <=== apply addall
Run Code Online (Sandbox Code Playgroud)
也就是说,你应该注意到Clojure没有尾调用优化,这意味着这个代码会因中等大小的输入而失败.Clojure鼓励使用loop/recur和内置序列处理功能.