简体   繁体   中英

Clojure - Using recursion to find the number of elements in a list

I have written a function that uses recursion to find the number of elements in a list and it works successfully however, I don't particularly like the way I've written it. Now I've written it one way I can't seem to think of a different way of doing it.

My code is below:

(def length 
 (fn [n]
  (loop [i n total 0]
   (cond (= 0 i) total
     :t (recur (rest i)(inc total)))))) 

To me it seems like it is over complicated, can anyone think of another way this can be written for comparison?

Any help greatly appreciated.

Here is code showing some different solutions. Normally, you should use the built-in function 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))))

Here is a naive recursive version:

(defn my-count [coll]
    (if (empty? coll) 
        0 
        (inc (my-count (rest coll)))))

Bear in mind there's not going to be any tail call optimization going on here so for long lists the stack will overflow.

Here is a version using reduce :

(defn my-count [coll]
    (reduce (fn [acc x] (inc acc)) 0 coll))

Here's one that is tail-call optimized, and doesn't rely on loop . Basically the same as Alan Thompson's first one, but inner functions are the best things. (And feel more idiomatic to me.) :-)

(defn my-count [sq]
 (letfn [(inner-count [c s]
          (if (empty? s) 
           c
           (recur (inc c) (rest s))))]
  (inner-count 0 sq)))

Just for completeness, here is another twist

(defn my-count
  ([data]
   (my-count data 0))
  ([data counter]
   (if (empty? data)
     counter
     (recur (rest data) (inc counter)))))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM