我不经常写宏。我从来没有遇到过这种情况,我希望defn
基于编译时已知的信息,从向量中defevent
。用例是在一个JS库的clojurescript中创建一个包装器lib,其中JS对象上有许多方法,我想用更多惯用的cljs函数包装。
与clojure macro to generate functions不同,这个问题取决于使用非文字参数调用宏,该参数作为表单(未计算)传递给宏,然后必须在宏返回代码之前对其进行求值形式。
下面,对core
的单独调用按预期工作,在on-x
的{{1}} ns内创建了一个函数。但是,在map
中调用events
,关键字矢量时,它会失败并显示:
WARNING: Use of undeclared Var foo.core/defevent at line 1 <cljs repl>
#object[TypeError TypeError: Cannot read property 'cljs$core$IFn$_invoke$arity$1' of undefined
我怀疑这是因为宏接收参数作为未评估的表单,并且在map
源代码中的某处,我的defevent
被调用的形式或多或少像(defevent (rest foo))
或某些形式...那么如何根据defevent
中的值重写(map defevent events)
或defn
代码以启用events
'函数?
macros.clj:
(ns foo.macros)
(defmacro defevent
[event-kw]
`(defn ~(symbol (str "on-" (name event-kw)))
[~'this ~'keyvec ~'cb]
(.call (aget ~'this ~(name event-kw))
~'this
~'keyvec
~'cb)))
core.cljs:
(ns foo.core
(:require-macros [foo.macros :refer [defevent]])
(defevent :x) ;; works
(def events [:a :b :c])
(doall (map defevent events)) ;; fails