交换!原子然后:java.lang.ClassCastException:java.lang.String无法强制转换为clojure.lang.IFn

时间:2012-08-30 21:44:51

标签: clojure

所以,在我的core.clj文件中,我有:

(def page-buffer (BufferedReader. (InputStreamReader. (clojure.java.io/input-stream               (clojure.java.io/resource "mitochondria.html")))))    
(def parsed-page (atom ""))

然后再说:

(defn -main [& args]
(let [port (Integer/parseInt (first args))]
(swap! parsed-page  (with-open []
                      (.toString (reduce #(.append %1 %2)
                                         (StringBuffer.) (line-seq page-buffer)))))
(println "Server is starting")
(println "port: " port)
(run-server port)))

这编译然后我把它变成一个uberjar。但是当我运行它时,我得到了掉线!爆炸:

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
at clojure.core$swap_BANG_.invoke(core.clj:2106)
at serve_pages_from_memory.core$_main.doInvoke(core.clj:29)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at serve_pages_from_memory.core.main(Unknown Source)

我在没有使用原子的情况下尝试了这一切并且一切正常(使用用“def”定义的var作为字符串)但最终我想将此var发送到多个线程,所以我需要将它作为一个原子或代理人。

我做错了什么?

更新:

杰拉米海勒,谢谢。固定,但结果是罪恶的丑陋:

(defn parse-buffer [& everything-else]
(with-open []
(.toString (reduce #(.append %1 %2)
                   (StringBuffer.) (line-seq page-buffer)))))

(defn -main [& args]
(let [port (Integer/parseInt (first args))]
(swap! parsed-page parse-buffer)
(println "Server is starting")
(println "port: " port)
(run-server port)))

我必须给parse-buffer一个参数或者我得到一个错误。但我不使用这个论点,所以这很难看。我一定是写错了,是吗?

1 个答案:

答案 0 :(得分:3)

您需要将函数传递给swap!。现在你传递一个值。

(let [foo (atom 1)]
  (swap! foo + 2)
  @foo)

上面的表达式将返回3.传入的函数获取atom的当前值,返回值成为atom的新值。任何额外的参数都会传递给给定的函数。


评论您的更新:是的,您需要为swap!中使用的函数提供参数。第一个参数是原子的当前值。但是,您无需破解parse-buffer即可使其正常运行。你可以用匿名函数包装它。

此外,parse-buffer可以大大简化。由于line-seq会返回给定阅读器的一系列行,并且str在内部使用StringBuilder,因此您只需将其应用于序列。

(defn parse-buffer []
  (with-open [buf page-buffer]
    (apply str (line-seq buf))))

(defn -main [& args]
  (let [port (Integer/parseInt (first args))]
    (swap! parsed-page (fn [cur-val] (parse-buffer)))
    (println "Server is starting")
    (println "port: " port)
    (run-server port)))