Reputation: 196
I'm having a lot of trouble with Clojure since I'm new to it. I'm attempting to solve for an orthanormal vector from matrix [[i, j, k], [5, 2, 3], [8, 3, 2]]. I know what the algorithm is, but I'm confused about when to use atoms and vars. As a result, I continue to get errors. Could someone point out what I'm doing wrong and how I can improve the code?
Listed below the code is the error.
(defn solve [& rows]
(let [orthanormal-vector (atom [])]
(let [dimension-range (range (count rows))
determinant-argument (atom [])]
(doseq [[i row] (map list dimension-range rows)]
(let [row-range (range (count row))
determinant-vector (atom [])]
(doseq [[j e] (map list row-range (seq row))]
(if-not (= i j) (swap! determinant-vector (conj determinant-vector e)) (println "Do nothing")))
(var-set determinant-argument (conj determinant-argument determinant-vector)))
(def determinant-result (incanter-core/det (incanter-core/matrix (vec determinant-argument))))
(swap! orthanormal-vector (conj orthanormal-vector determinant-result))
))))
java.lang.ClassCastException: clojure.lang.Atom cannot be cast to clojure.lang.IPersistentCollection
core.clj:83 clojure.core/conj
/Users/chriskim/Desktop/promethix/src/promethix/orthanormal/solver.clj:14 promethix.orthanormal.solver/solve
RestFn.java:436 clojure.lang.RestFn.invoke
/Users/chriskim/Desktop/promethix/src/promethix/orthanormal/solver.clj:24 promethix.orthanormal.solver/eval16321
Compiler.java:6703 clojure.lang.Compiler.eval
Compiler.java:6666 clojure.lang.Compiler.eval
core.clj:2927 clojure.core/eval
eval.clj:77 lighttable.nrepl.eval/->result
AFn.java:156 clojure.lang.AFn.applyToHelper
AFn.java:144 clojure.lang.AFn.applyTo
core.clj:626 clojure.core/apply
core.clj:2468 clojure.core/partial[fn]
RestFn.java:408 clojure.lang.RestFn.invoke
core.clj:2559 clojure.core/map[fn]
LazySeq.java:40 clojure.lang.LazySeq.sval
LazySeq.java:49 clojure.lang.LazySeq.seq
RT.java:484 clojure.lang.RT.seq
core.clj:133 clojure.core/seq
core.clj:2595 clojure.core/filter[fn]
LazySeq.java:40 clojure.lang.LazySeq.sval
LazySeq.java:49 clojure.lang.LazySeq.seq
Cons.java:39 clojure.lang.Cons.next
RT.java:598 clojure.lang.RT.next
core.clj:64 clojure.core/next
core.clj:2856 clojure.core/dorun
core.clj:2871 clojure.core/doall
eval.clj:126 lighttable.nrepl.eval/eval-clj
RestFn.java:442 clojure.lang.RestFn.invoke
eval.clj:192 lighttable.nrepl.eval/eval10834[fn]
AFn.java:152 clojure.lang.AFn.applyToHelper
AFn.java:144 clojure.lang.AFn.applyTo
core.clj:624 clojure.core/apply
core.clj:1862 clojure.core/with-bindings*
RestFn.java:425 clojure.lang.RestFn.invoke
eval.clj:177 lighttable.nrepl.eval/eval10834[fn]
eval.clj:176 lighttable.nrepl.eval/eval10834[fn]
MultiFn.java:227 clojure.lang.MultiFn.invoke
core.clj:98 lighttable.nrepl.core/queued[fn]
core.clj:2402 clojure.core/comp[fn]
interruptible_eval.clj:138 clojure.tools.nrepl.middleware.interruptible-eval/run-next[fn]
AFn.java:22 clojure.lang.AFn.run
ThreadPoolExecutor.java:895 java.util.concurrent.ThreadPoolExecutor$Worker.runTask
ThreadPoolExecutor.java:918 java.util.concurrent.ThreadPoolExecutor$Worker.run
Thread.java:680 java.lang.Thread.run
Upvotes: 0
Views: 713
Reputation: 106401
This is not quite answering your question but I'd suggest using core.matrix
for matrix computation / algorithms in Clojure. This gives you at least two big advantages:
Disclaimer: I'm a maintainer on some of the above projects.
Upvotes: 1
Reputation: 91607
The specific error resulting in clojure.lang.Atom cannot be cast to clojure.lang.IPersistentCollection
is:
(swap! determinant-vector (conj determinant-vector e))
shoudl be written:
(swap! determinant-vector conj e)
swap! takes an atom as it's first argument and a function as a second argument. It then builds a function call by passing the current value in the atom as the first argument to that function and appends the rest of the arguments after that. this will be translated into a function call somewhat like this:
(conj @determinant-vector e)
ps: @ is a reader macro for calling deref
to get the current value out of one of the mutable state types.
PPS: Charles Duffy is correct that loop/recur are much better tools for this task than using an atom. It should be about 100x faster, at least in terms of overhead.
Upvotes: 1