使用递归创建clojure添加函数

Lia*_*yan 1 recursion clojure

我正试图用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)

Mat*_*ick 7

看起来你的括号是错误的 - 你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和内置序列处理功能.