List Clojure-使用递归查找列表中的元素数
我已经编写了一个函数,它使用递归来查找列表中的元素数量,并且工作得很成功。但是,我并不特别喜欢我编写它的方式。现在我已经用一种方式写了,我似乎想不出另一种方式来写 我的代码如下:List Clojure-使用递归查找列表中的元素数,list,recursion,clojure,List,Recursion,Clojure,我已经编写了一个函数,它使用递归来查找列表中的元素数量,并且工作得很成功。但是,我并不特别喜欢我编写它的方式。现在我已经用一种方式写了,我似乎想不出另一种方式来写 我的代码如下: (def length (fn [n] (loop [i n total 0] (cond (= 0 i) total :t (recur (rest i)(inc total)))))) 对我来说,它似乎太复杂了,有人能想出另一种方法来写它进行比较吗 非常感谢您的帮助。以下是显示一些不同解
(def length
(fn [n]
(loop [i n total 0]
(cond (= 0 i) total
:t (recur (rest i)(inc total))))))
对我来说,它似乎太复杂了,有人能想出另一种方法来写它进行比较吗
非常感谢您的帮助。以下是显示一些不同解决方案的代码。通常,您应该使用内置函数
count
(def data [:one :two :three])
(defn count-loop [data]
(loop [cnt 0
remaining data]
(if (empty? remaining)
cnt
(recur (inc cnt) (rest remaining)))))
(defn count-recursive [remaining]
(if (empty? remaining)
0
(inc (count-recursive (rest remaining)))))
(defn count-imperative [data]
(let [cnt (atom 0)]
(doseq [elem data]
(swap! cnt inc))
@cnt))
(deftest t-count
(is (= 3 (count data)))
(is (= 3 (count-loop data)))
(is (= 3 (count-recursive data)))
(is (= 3 (count-imperative data))))
下面是显示一些不同解决方案的代码。通常,您应该使用内置函数
count
(def data [:one :two :three])
(defn count-loop [data]
(loop [cnt 0
remaining data]
(if (empty? remaining)
cnt
(recur (inc cnt) (rest remaining)))))
(defn count-recursive [remaining]
(if (empty? remaining)
0
(inc (count-recursive (rest remaining)))))
(defn count-imperative [data]
(let [cnt (atom 0)]
(doseq [elem data]
(swap! cnt inc))
@cnt))
(deftest t-count
(is (= 3 (count data)))
(is (= 3 (count-loop data)))
(is (= 3 (count-recursive data)))
(is (= 3 (count-imperative data))))
下面是一个简单的递归版本:
(defn my-count [coll]
(if (empty? coll)
0
(inc (my-count (rest coll)))))
请记住,这里不会进行任何尾部调用优化,因此对于长列表,堆栈将溢出
以下是使用reduce
的版本:
(defn my-count [coll]
(reduce (fn [acc x] (inc acc)) 0 coll))
下面是一个简单的递归版本:
(defn my-count [coll]
(if (empty? coll)
0
(inc (my-count (rest coll)))))
请记住,这里不会进行任何尾部调用优化,因此对于长列表,堆栈将溢出
以下是使用reduce
的版本:
(defn my-count [coll]
(reduce (fn [acc x] (inc acc)) 0 coll))
为了完整起见,这里有另一个转折点
(defn my-count
([data]
(my-count data 0))
([data counter]
(if (empty? data)
counter
(recur (rest data) (inc counter)))))
为了完整起见,这里有另一个转折点
(defn my-count
([data]
(my-count data 0))
([data counter]
(if (empty? data)
counter
(recur (rest data) (inc counter)))))
这里有一个是尾部调用优化的,不依赖于
循环
。基本上与艾伦·汤普森的第一部相同,但内部功能是最好的。(而且对我来说感觉更地道。):-)
这里有一个是尾部调用优化的,不依赖于
循环
。基本上与艾伦·汤普森的第一部相同,但内部功能是最好的。(而且对我来说感觉更地道。):-)
为什么不直接使用呢?我必须使用递归使它工作,这就是为什么我一直使用循环的原因,也是为什么它变得如此复杂的原因。递归地使用count有意义吗?使用
loop recur
你只有一个循环,而不是递归。loop/recur在概念上与递归函数是一样的——这就是为什么“recur”是名称的一部分。它在JVM上以循环的形式实现,但是如果你将它移植到scheme,你将使用递归函数来实现它。@amalloy,我想应该指出scheme已经按照它的标准进行了要求,所以如果我没有误解你的“实现为递归函数”最有可能的结果是循环,因此与通过关键字的显式尾部调用相同(如recur
is)。-除非它是自动完成的为什么不直接使用?我必须使用递归使它工作,这就是为什么我一直在使用循环,为什么它会如此复杂。递归地使用count有意义吗?使用loop recur
你只有一个循环,而不是递归。loop/recur在概念上与递归函数是一样的——这就是为什么“recur”是名称的一部分。它在JVM上以循环的形式实现,但是如果你将它移植到scheme,你将使用递归函数来实现它。@amalloy,我想应该指出scheme已经按照它的标准进行了要求,所以如果我没有误解你的“实现为递归函数”最有可能的结果是循环,因此与通过关键字的显式尾部调用相同(如recur
is)。-除非它是自动完成的为什么还要提到如何用原子来做呢?这是一种任何人都会反对的反模式;如果您想在其他两种好方法的基础上添加第三种方法,那么reduce就是要展示的功能。有时候,命令式/可变方法是最简单的答案(显然,对于本例来说,除了计数之外的所有方法都是多余的)。如果没有人能看到的代码是命令式的或可变的,并且不会泄露出去,那么为什么还要担心呢?如果你挖得足够深,一切都是可变的/必须的。只有当它泄漏出来时才成为问题。这是一种非常面向图灵机器的思维方式。或者你可以说,如果你挖得足够深,一切都是递归的(lambda演算)。只有当您必须在现实生活中的现代物理处理器上实际实现它时,必要的实现细节才会泄露出来。为什么还要提到如何使用atom来实现呢?这是一种任何人都会反对的反模式;如果您想在其他两种好方法的基础上添加第三种方法,那么reduce就是要展示的功能。有时候,命令式/可变方法是最简单的答案(显然,对于本例来说,除了计数之外的所有方法都是多余的)。如果没有人能看到的代码是命令式的或可变的,并且不会泄露出去,那么为什么还要担心呢?如果你挖得足够深,一切都是可变的/必须的。只有当它泄漏出来时才成为问题。这是一种非常面向图灵机器的思维方式。或者你可以说,如果你挖得足够深,一切都是递归的(lambda演算)。只有当您必须在现实生活中的现代物理处理器上实际实现它时,必要的实现细节才会泄漏出来。