Clojure - sum up a bunch of numbers

clojure, lisp

Solution

In Clojure - and at large in functional programming - we avoid assignment as it destroys state history and makes writing concurrent programs a whole lot harder. In fact, Clojure doesn't even support assignment. An `atom` is a reference type that is thread safe.

Another common trait of functional programming is that we try to solve problems as a series of data transformations. In your case you case some data, a list of numbers from 0 to 1000 exclusive, and you need to obtain the sum of all numbers that match a predicate. This can certainly be done by applying data transformations and completely removing the need for assignment. One such implementation is this:

(->> (range 1000)
     (filter #(or (= (rem % 3) 0) (= (rem % 5) 0)))
     (reduce +))

Please understand that a function such as the one you wrote isn't considered idiomatic code. Having said that, in the interest of learning, it can be made to work like so:

(defn sum-of-multiples [max]
  (let [result (atom 0)]
    (doseq [i (range max)] 
      (if (or (= (rem i 3) 0) (= (rem i 5) 0))
        (swap! result #(+ % i)))    
      )
    @result))

(sum-of-multiples 1000)

`for` returns a lazy sequence but since you're simply interested in the side-effects caused by `swap!` you need to use `doseq` to force the sequence. The other problem is that the second argument to `swap!` is a function, so you don't need to deref `result` again.

Problem

Hey I'm doing a Project Euler question, and I'm looking to sum up all the numbers under 1000 that are multiplies of 3 or 5. But being a clojure noob, my code just keeps returning zero.. and I'm not sure why. ``` (defn sum-of-multiples [max] (let [result (atom 0)] (for [i (range max)] (if (or (= (rem i 3) 0) (= (rem i 5) 0)) (swap! result (+ @result i))) ) @result)) (sum-of-multiples 1000) ``` Also the line `(swap! result (+ @result i)))` bugs me.. In C# I could do `result += i`, but I'm guessing there must be a better way to this in Clojure?

Original source