如何在Clojurescript中共享宏中的原子?

时间:2012-10-02 05:05:25

标签: macros clojure clojurescript

我在clj(clojure)命名空间中有以下代码。

(ns project.clojure.clojurescript-macros)

(def trace-history (atom []))

; hmm, you could run out of memory on recursive functions here?
; Fortunately functions aren't actually recursive in clojure. :]
(defmacro push-args [name args]
  `(swap! trace-history
     (fn [stack#]
       (conj stack# [~name (zipmap ~(vec (map str args)) ~args)]))))

(push-args :hello [:a :b :c])

在另一个cljs(clojurescript)命名空间中,我有以下

(ns project.clojurescript.user   
  (:require-macros [project.clojure.clojurescript-macros :as c]))

(c/push-args :hello [:a :b :c])

我编译了我的clojurescript代码,并在我的浏览器中打开它,不幸的是,我收到以下错误。

Uncaught TypeError: Cannot read property 'trace_history' of undefined main.js:22348
(anonymous function)                                                  main.js:22348

在我编译的clojurescipt代码中查看第22348行,我看到以下内容。

cljs.core.swap_BANG_.call(null, project.clojure.trace_history, function(stack__6402__auto__) {
  return cljs.core.conj.call(null, stack__6402__auto__, 
    cljs.core.PersistentVector.fromArray(["\ufdd0'hello", 
      cljs.core.zipmap.call(null, 
        cljs.core.PersistentVector.fromArray([":a", ":b", ":c"], true),          
        cljs.core.PersistentVector.fromArray(["\ufdd0'a", "\ufdd0'b", "\ufdd0'c"], 
      true))], 
    true))
  });

问题是project.clojure.trace_history尚未在main.js中的任何位置定义。我明白什么是错的,但我不确定如何解决它。我尝试过其他解决方案,例如将跟踪历史记录放在共享的clojure文件中,并将跟踪历史记录放在cljs文件本身中。似乎没有工作。鉴于我想在这个宏的所有编译之间有一个共享的全局原子,我怎么能在Clojurescript中这样做呢?

1 个答案:

答案 0 :(得分:3)

原子是运行时数据,宏是编译时构造。对于宏来说,拥有一个“共享全局原子”并没有多大意义 - 你的宏所做的就是编译成代码,只需期望在那里有一个名为trace-history的符号目前的NS。

如果您只想编写可以使用原子的公共代码,那么您应该将其编写为可以将原子作为参数,而不是通过硬编码符号名称来假设它的存在。 / p>

如果您的意思是希望在Clojure + ClojureScript应用程序的客户端和服务器上都可以使用相同的atom值,则需要编写自己的代码以通过Ajax调用来协调值...这是不是语言中的内容。