40
votes

I have a function that takes the number of years and salary, then recursively doubles the salary until years is exhausted. However, I keep getting this error:

ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn

The Code

(defn calculate-salary
    [years salary]
    (if (= years 0)
        (salary)
        (calculate-salary (- years 1) (* salary 2))))

I'm very new to Clojure so I'm sure its something simple, but I just can't seem to figure it out.

4
To be fair, everyone below answered correctly, but I can only mark one as accepted.Jack Slingerland

4 Answers

51
votes

The error's meaning shouldn't be too hard to sort out: a number is being used where a function is expected.

Parenthesis in Clojure are not a grouping construct, they are used primarily to invoke function calls. If you change (salary) to salary you will return the number rather than attempting to call it as a no-argument function.

8
votes

Since you are new I rewrote your function to be a bit more idiomatic. Also, it uses recur so it will not consume the call stack.

(defn calculate-salary
  [years salary]
  (if (zero? years)
    salary
    (recur (dec years) (* salary 2))))

Notice the use of the zero? predicate, recur, and dec

EDIT: typos and grammar

6
votes

This

(salary)

is a function call, but salary is not a function -- it's a number.

The solution is to not wrap it in parentheses:

(if (= years 0) salary (calculate-salary (- years 1) (* salary 2)))
4
votes

You need to remove the brackets from around salary in your if condition:

(if (= years 0)
        salary
        (calculate-salary (- years 1) (* salary 2))

the form (f arg1 arg2 ..) attempts to call f as a function with arg1, arg2 ... as arguments. Therefore (salary) attempts to invoke salary (a long) as a function with no arguments, hence the error.