code123456
code123456

Reputation: 98

Understanding recur

Trying out this snippet of code and doesn't seem to be working quite right..

(defn- multiple_of?
  [div num]
  (= (mod num div) 0))

(defn sum_of_multiples_from 
  ([start] (sum_of_multiples_from start 0))
  ([start total]
   (if (<= start 0)
     total
     (recur (dec start) (or (multiple_of? 3 start) (multiple_of? 5 start)
                            (+ total start) start)))))

I receive the following error:

java.lang.Boolean cannot be cast to java.lang.Number

I am guessing it has to do with:

(recur (dec start) (or (multiple_of? 3 start) (multiple_of? 5 start)
                            (+ total start)
                            start)))))

But I'm not sure why, I'm new to clojure, so I'm trying to get a grasp of recur.

Upvotes: 1

Views: 98

Answers (2)

Diego Basch
Diego Basch

Reputation: 13069

You really want a conditional expression for your recur, and one that always returns a number. For example:

(defn sum_of_multiples_from
  ([start] (sum_of_multiples_from start 0))
  ([start total]
    (if (<= start 0)
      total
      (recur (dec start)
         (if  (or (multiple_of? 3 start) (multiple_of? 5 start))
           (+ total start)
           total)))))

Note that this is a weird way to implement this in a functional language. You're really picking values from a range and adding them up, so it's better to implement this as a filter and a reduce, for example:

(reduce + (filter #(or (multiple_of? 3 %) (multiple_of? 5 %)) (range 50)))
=> 543

Upvotes: 4

Max Noel
Max Noel

Reputation: 8910

Your or call returns a boolean ((multiple_of? 3 start)) as soon as start is a multiple of 3.

In Clojure, or always returns one of its arguments -- either the first truish one if one exists, or the last falsish one otherwise.

Upvotes: 3

Related Questions