Clojure - 我能做些什么来正确使用Vars和/或Atoms?

时间:2014-06-28 01:22:36

标签: variables clojure

我对Clojure有很多麻烦,因为我是新手。我试图从矩阵[[i,j,k],[5,2,3],[8,3,2]]求解一个正规矢量。我知道算法是什么,但我很困惑何时使用原子和变量。结果,我继续得到错误。有人可以指出我做错了什么以及如何改进代码?

下面列出的代码是错误。

(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

2 个答案:

答案 0 :(得分:1)

导致clojure.lang.Atom cannot be cast to clojure.lang.IPersistentCollection的具体错误是:

(swap! determinant-vector (conj determinant-vector e))
shoudl写道:

(swap! determinant-vector conj e)

交换!将原子作为第一个参数,将函数作为第二个参数。然后,它通过将atom中的当前值作为该函数的第一个参数传递并在此之后附加其余参数来构建函数调用。这将被翻译成函数调用,有点像这样:

(conj @determinant-vector e)

ps:@是一个读取器宏,用于调用deref以从其中一个可变状态类型中获取当前值。

PPS:Charles Duffy认为循环/重复是很多更好的工具,而不是使用原子。它应该快约100倍,至少在开销方面。

答案 1 :(得分:1)

这并没有完全回答你的问题,但我建议在Clojure中使用core.matrix进行矩阵计算/算法。这为您提供了至少两大优势:

  • 已经实现了许多向量/矩阵运算。如果你不需要重新发明轮子,那就没什么意义了。
  • 它允许您使用比常规Clojure数据结构更高效的 的优化实现。这包括原生BLAS库(例如Clatrix)和快速纯JVM矩阵库(例如Vectorz

免责声明:我是上述某些项目的维护者。