卡在Clojure递归中

时间:2013-10-24 09:42:26

标签: recursion clojure

我正在尝试在clojure中编写递归函数。该函数返回最大数量的给定集合。如果集合是emty,那么它应该返回nil。 我的代码是:

(defn gum [coll]
 (if (empty? coll)
  0 
  (max (first coll)
   (gum (rest coll)))))

预期结果:

(gum [1 2 98 -3]) => 98
(gum [1 9]) => 9
(gum []) => nil

但我得到了:

(gum [1 2 98 -3]) => 98
(gum [1 9]) => 9
(gum []) => 0 (not desired result - should be `nil`)

这是因为我将(empty? coll)的值保持为0。如果我将其保留为nil,则(gum [1 2 98 -3])将无效。有关如何将(gum [])的{​​{1}}和nil的价值同时作为(gum [1 2 98 -3])的任何建议?

5 个答案:

答案 0 :(得分:2)

我想你想要这样的东西:

(defn gum [[head & tail]]
  (if (empty? tail)
      head
      (max head (gum tail))))

我在这里使用的是解构而不是firstrest,但它与以下内容相同:

(defn gum [coll]
  (let [head (first coll)
        tail (rest coll)]
    (if (empty? tail)
        head
        (max head (gum tail)))))

但你应该尽量避免像(max head (gum tail))这样的结构,因为Clojure无法优化它。尽可能尝试使用recur尾递归:

(defn gum [[head & tail]]
  (if (empty? tail)
      head
      (recur (cons (max head (first tail))
                   (rest tail)))))

recur允许Clojure使用Tail Call Optimization将递归调用转换为迭代调用,允许它在常量堆栈空间中运行。它不仅可以使您的代码更快,还可以防止堆栈溢出。

您还应该考虑使用高阶函数而不是递归(如SaltyEgg suggested):

(defn gum [coll]
  (if-let [s (seq coll)]
    (reduce max s)))

在大多数情况下,它们提供了更简单的解决方案并且它们非常优化。

答案 1 :(得分:1)

试试这个:

(defn gum [coll]
 (if (empty? coll)
  nil 
  (reduce max coll)))

答案 2 :(得分:0)

您似乎正在尝试重新定义max功能?

现在,如果您想了解max函数的工作原理,那么在repl中查看源(source max)通常是一个好主意:

(defn max
  "Returns the greatest of the nums."
  {:added "1.0"
   :inline-arities >1?
   :inline (nary-inline 'max)}
  ([x] x)
  ([x y] (. clojure.lang.Numbers (max x y)))
  ([x y & more]
   (reduce1 max (max x y) more)))

请注意,(apply max [])会抛出异常,而不是返回nilArityException Wrong number of args (0) passed to: core/max clojure.lang.AFn.throwArity (AFn.java:429)

编辑: 这就是为什么首先检查我们是否要应用max然后(可能)应用的方法,如其他答案所示:

(defn gum [coll]
  (if-let [s (seq coll)]
    (reduce max s)))

答案 3 :(得分:0)

你不应该在里面调用相同的函数,因为Clojure没有尾递归优化(TRO)。使用(recur arg1 arg2 etc)迭代下一步。并且不要忘记添加if语句来离开递归。

答案 4 :(得分:0)

使用与您描述的逻辑相同的方法,可以返回单例元素而不是零:

(defn gum [coll]
  (if (or (empty? coll) 
          (singleton? coll))
    (first coll)
    (max (first coll) (gum (rest coll)))))

具有:

(defn singleton? [coll]
  (if (first coll) (empty? (rest coll)) false))