我可以编写一个Clojurescript宏来定义另一个命名空间中的函数吗?
在使用宏的命名空间中定义函数非常简单:
mac.clj中定义的宏
(ns nut.mac)
(defmacro def-foo
"Define a trivial function in the *current* namespace named ``fn-name''."
[fn-name]
`(defn ~(symbol fn-name) [] ~(str "It's " fn-name ".")))
;; (macroexpand '(def-foo "bar"))
;; => (def bar (clojure.core/fn ([] "It's bar.")))
在foo.cljs中调用的宏
(ns nut.foo
(:require-macros [nut.mac :refer [def-foo def-ns-foo]]))
(def-foo "a-function") ;; creates nut.foo.a-function
我希望宏在不同的命名空间中创建一个函数。 这样的事情(赢得了工作):
(ns nut.mac)
(defmacro def-ns-foo
"Define a trivial function in the *specified* namespace named ``fn-name''."
[namespace-name fn-name]
`(do (ns ~(symbol namespace-name))
(defn ~(symbol fn-name) [] ~(str "It's " fn-name "."))))
;; (macroexpand '(def-ns-foo "nut.x" "bar"))
;; => (do (clojure.core/ns nut.x) (clojure.core/defn bar [] "It's bar."))
然后在nut.foo命名空间中调用宏:
(ns nut.foo
(:require-macros [nut.mac :refer [def-ns-foo]]))
(def-ns-foo "nut.x" "baz")
;; WARNING: Use of undeclared Var cljs.core/ns at line 8
很明显,在编译时特别处理文件顶层的ns表单。
像这样的东西(所有在一个文件中),但它有点乏味:
(ns nut.foo
(:require-macros [nut.mac :refer [def-foo]]))
(ns nut.x)
(def-foo "baz")
(ns nut.y)
(def-foo "baz")
(ns nut.z)
(def-foo "baz")
我已经开始关注cljs.analyzer.api了,但老实说,理解这可能比它现在的价值更麻烦。
在Clojurescript宏中创建命名空间是不可能的,或者可能只是错误的?