回顾我的初学者clojure反转函数

回顾我的初学者clojure反转函数,clojure,Clojure,我刚刚开始我的clojure之旅,我想知道是否有人能指出我下面函数中的初学者错误,这只是颠倒了列表。我知道已经有了一个反向函数,所以这纯粹是为了学习 (defn rev ([l] (if (= (count l) 1) l (rev '() l))) ([l orig] (if (= (count orig) 0) l (rev (conj l (first orig)) (rest orig))))) 在我的辩护中,它确实有效,但我发现自己在cloju

我刚刚开始我的clojure之旅,我想知道是否有人能指出我下面函数中的初学者错误,这只是颠倒了列表。我知道已经有了一个反向函数,所以这纯粹是为了学习

(defn rev
  ([l]
   (if (= (count l) 1) l (rev '() l)))
  ([l orig]
   (if (= (count orig) 0)
     l
     (rev (conj l (first orig)) (rest orig)))))

在我的辩护中,它确实有效,但我发现自己在clojure中经常做的事情是重载参数列表,以便在我需要一个工作列表时加以考虑,如本例中我将新项连接到的工作列表。

如果您不想用其他算术公开函数,请在本地定义并使用它们:

(defn rev [l]
  ((fn rev2 [l orig]
     (if (empty? orig)
       l
       (rev2 (conj (first orig) l) (rest orig))))
   () l))
您可能会发现使用let或letfn更容易:

顺便说一下

如果你只是想知道是否有,不要计算序列 里面有什么。使用seq或empty?。 去掉1元素序列的特例:它不是特例。 不需要引用。 当然,我们可以也应该使用recur而不是rev2的递归调用,以避免在长序列上破坏堆栈:

(defn rev [l]
  (letfn [(rev2 [l orig]
             (if (empty? orig)
                l
                (recur (conj l (first orig)) (rest orig))))]
    (rev2 () l)))

首先,首先查看现有的函数实现是一个非常好的主意:

(defn reverse [coll]
  (reduce conj () coll))
与代码的主要区别在于,现有的reverse实现使用高阶函数。尽可能使用高阶函数而不是递归是一种很好的做法

-

但是让我们假设您的目标是学习递归。下面是我应该如何写的:

(defn rev
  ([coll]
    (rev coll ()))
  ([coll acc]
    (if-let [[h & ts] (seq coll)]
      (recur ts (conj acc h))
      acc)))
让我们仔细看看我的代码

首先,我使用and检查coll是否为非空集合

然后我用它来获取给定集合的第一个元素和它的其余部分

换句话说,我的建筑

(if-let [[h & ts] (seq coll)]
  (recur ts (conj acc h))
  acc)
可以重写为if、let、first和rest:

这几乎就是你自己写的

最后一件重要的事情是,我正在使用,而不是直接调用rev。 它允许clojure编译器执行尾部递归优化

您还应该考虑使用,而不是创建重载函数,除非您想公开两个参数:

(defn rev [coll]
  (loop [coll coll
         acc  ()]
    (if-let [[h & ts] (seq coll)]
      (recur ts (conj acc h))
      acc)))
-

因此,代码中有很多地方需要改进。但我只能看到三个真正的错误:

你应该使用recur; 检查没有意义=计数l 1; 您应该使用而不是=count orig 0。 在这里,我修复了代码中的两个错误:

(defn rev
  ([l]
   (rev '() l))
  ([l orig]
   (if (empty? orig)
     l
     (recur (conj l (first orig)) (rest orig)))))

这个问题似乎离题了,因为它是关于代码审查的-那么为什么会有代码审查标签?@dagda1发布关于代码审查工具的问题?@dagda1我真的相信顺便说一句,你可以在@dagda1上提出关于这个的讨论。自从你发表评论后,我做了一些编辑。请检查我答案的最终版本。
(defn rev [coll]
  (loop [coll coll
         acc  ()]
    (if-let [[h & ts] (seq coll)]
      (recur ts (conj acc h))
      acc)))
(defn rev
  ([l]
   (rev '() l))
  ([l orig]
   (if (empty? orig)
     l
     (recur (conj l (first orig)) (rest orig)))))