在宏中动态创建Clojurescript命名空间?

时间:2016-04-23 17:46:19

标签: clojurescript

我可以编写一个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宏中创建命名空间是不可能的,或者可能只是错误的?

0 个答案:

没有答案