Reputation: 3
I'm new to clojure and I am trying to make a small program that does math with complex numbers. I've tried multiple versions of the multiply function and they all give the same error. For some other functions, using let fixed it but not here. im-make just returns a vector with the real and imaginary numbers.
(defn im-mult
([i j]
(let [a (first i)
b (second i)
x (first j)
y (second j)]
(im-make (- (* (a) (b)) (* (x) (y)))
(+ (* (a) (b)) (* (x) (y)))))))
given two vectors with a real and imaginary number, => (im-mult x y)
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn ComplexMath.core/im-mult (NO_SOURCE_FILE:7)
I just want to say, wow! Didn't think clojure had this much backing around here, thanks for the suggestions, the error was of course parenthesis and incorrect multiplying.
Upvotes: 0
Views: 114
Reputation: 70201
1) you need to get rid of the extra parens around a, b, x, and y.
2) anytime you see a bunch of first and second, that's a good clue that you should be destructuring your inputs instead:
(defn im-mult
[i j]
(let [[a b] i
[x y] j]
(im-make (- (* a b) (* x y))
(+ (* a b) (* x y)))))
I would always recommend this over #1. This might be a good place to stop for readability, but for grins we can keep pushing it...
3) I observe that (* a b) and (* x y) are used twice, so there is really no need to destructure at all - we can just apply * to i and j:
(defn im-mult
[i j]
(let [ab (apply * i)
xy (apply * j)]
(im-make (- ab xy)
(+ ab xy))))
4) I observe that you're applying the same operation to both inputs, so might as well map the operation across the inputs.
(defn im-mult
[i j]
(let [m (map #(apply * %) [i j])]
(im-make (apply - m)
(apply + m))))
5) Same observation for - and +...
(defn im-mult
[i j]
(let [m (map #(apply * %) [i j])
s (map #(apply % m) [- +])]
(apply im-make s)))
At this point, it's admittedly harder to see the intent of the code. However, I think one reason is that you've fixed the number of inputs to 2. My suspicion is that there is an n-dimensional algorithm here and taking [& i] as inputs would lead you to a more beautiful place while also improving the code.
Upvotes: 2
Reputation: 34252
Those extra parentheses aroung a
, b
, x
and y
are not needed. Besides, they make Clojure try to interpret numbers as functions. This should fix it:
(defn im-mult
([i j]
(let [a (first i)
b (second i)
x (first j)
y (second j)]
(im-make (- (* a b) (* x y))
(+ (* a b) (* x y))))))
Upvotes: 0