Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining my own max function with variable arguments

I'm learning Clojure solving the problems listed on 4clojure. One of the exercises is to create your own max function with variable arguments.

I'm trying to solve this easy problem using the REPL and I got to this solution:

(defn my-max 
    [first & more] (calc-max first more))

(defn calc-max 
    [m x] 
        (cond (empty? x) m
            (> (first x) m) (calc-max (first x) (rest x))
            :else calc-max m (rest x)))

Which works fine but the exercise doesn't allow the use of def and therefore I must crunch both functions into one. When I replace the calc-max reference with its code the result is:

(defn my-max 
    [first & more] 
    ((fn calc-max 
        [m x] 
            (cond (empty? x) m
                (> (first x) m) (calc-max (first x) (rest x))
                :else calc-max m (rest x)))
                    first more))

But this code doesn't work and returns the next error:

user=> (my-max 12 3 4 5 612 3)
java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0)

I guess this error comes from trying to evaluate the result of the calc-max function and I guess it's a syntax error on my part, but I can't figure out how to resolve it.

like image 924
eliocs Avatar asked Sep 21 '11 16:09

eliocs


2 Answers

Here is the function I used to solve it. The point is not to use max at all.

(fn [& args] (reduce (fn [x y] (if (> x y) x y) ) args ) )
like image 70
Justin Thomas Avatar answered Oct 17 '22 02:10

Justin Thomas


Real error is that you called parameter first - it rebinds real first function to number! Just change name to something other, and your variant will work. Although it maybe better explicitly name function, instead of calling anonymous function, for example, you can declare calc-max as local function using letfn, for example. So your my-max will look like:

(defn my-max [ff & more]
  (letfn [(calc-max [m x] 
            (cond (empty? x) m
                  (> (first x) m) (calc-max (first x) 
                                            (rest x))
                  :else (calc-max m (rest x))))]
    (calc-max ff more)))

Although, I think, that you can write simpler code:

(defn my-max [& more] (reduce max more))
like image 8
Alex Ott Avatar answered Oct 17 '22 02:10

Alex Ott