问题
So I am trying to re-implement the reduce method, so it can add a couple of numbers that normally can be done using reduce, like:
(reduce + [1 2 3]) ;; 6
(newRd + [1 2 3])  ;; 6
So I thought maybe it can be done using a recursive function that adds the first element of the vector every time it is called and do it again for the rest of the vector. Something like this:
(defn newRd [list]
  (let [sum 0]
    (if (not= 0 (count list))
      (+ sum (first list))
      (newRd (rest list))
      )
    )
  )
I think I am not doing local storing correctly. Any suggestion or maybe a better approach?
回答1:
there are two mistakes here in your code:
1) you don't add your current sum to the recursive call result
2) you should return zero when the list is empty
corrected variant:
(defn newRd [list]
  (let [sum 0]
    (if (not= 0 (count list))
      (+ sum (first list)
         (newRd (rest list)))
      sum)))
in repl:
user> (newRd [1 2 3 4])
10
next, you can update it a bit:
first you don't really need the sum in let statement, since the sum always = 0
second, there is a lib function empty? to check if list is empty.
(defn newRd [list]
  (if-not (empty? list)
    (+ (first list)
       (newRd (rest list)))
    0))
but remember: clojure doesnt'do tail call optimization, so it is easy to cause stack owerflow with a long list:
user> (newRd (repeat 1000000 1))
StackOverflowError   user/newRd (form-init289434844644272272.clj:73)
so it's preferable to use loop/recur
(defn sum-list [list]
  (loop [list list sum 0]
    (if (empty? list)
      sum
      (recur (rest list) (+ sum (first list))))))
in repl:
user> (sum-list (repeat 1000000 1))
1000000
the other option is to make the function itself tail recursive:
(defn newRd [list sum]
  (if-not (empty? list)
    (recur (rest list) (+ sum (first list)))
    sum))
user> (newRd (repeat 1000000 1) 0)
1000000
then you can add the additoinal arity, for not to pass the second parameter in every call:
(defn newRd
  ([list] (newRd list 0))
  ([list sum]
   (if-not (empty? list)
     (recur (rest list) (+ sum (first list)))
     sum)))
    回答2:
Further to leetwinksi's answer ...
You might as well implement new-reduce (camel case is not idiomatic) in general: 
(defn new-reduce
  ([f init coll]
   (if (seq coll)
     (recur f (f init (f init (first coll))) (rest coll))
     init))
  ([f coll]
   (if (seq coll)
     (reduce f (first coll) (rest coll))
     (f))))
Then
(new-reduce + [1 2 3]) ;; 6
This is more or less what the source code for reduce looked like until recently, if you stripped chunking out. 
The two-argument version that you use leans on the three-argument version, which you can recur on directly, without an explicit loop. This entails passing f each time, but that's what it used to do. Presumably it's faster to carry an extra argument than to work in a local scope. 
来源:https://stackoverflow.com/questions/35145965/adding-the-elements-of-a-vector-without-using-reduce-or-apply