我正在构建一个应该像这样调用的宏:
(myMacro MyController something otherthing
(defn onFoo [this event]
(println "ok"))
(defn onBar [this event]
(println "ok"))
)
在前三个参数之后,我希望能够传递一些函数,这些函数应该用于在宏的(definterface
和(deftype
部分中构建函数定义。
上述调用的结果应为:
(definterface IMyController
(^void onFoo [^javafx.event.ActionEvent event])
(^void onBar [^javafx.event.ActionEvent event])
)
(deftype MyController []
IHandler (^{javafx.fxml.FXML {}} onFoo [this event] (println "ok"))
IHandler (^{javafx.fxml.FXML {}} onBar [this event] (println "ok"))
)
我是Clojure的新手,但FXML文件控制器的手工构建实现已经有效了,我只是想用宏来简化它,但是我无法找到任何有关如何做这方面的帮助宏定义中的循环。
更新
宏几乎已经完成,并且已经成功运行。
(defmacro viewHandler [className & fn-defs]
(def interface (symbol (join ["I" className])))
`(do
(definterface ~interface
~@(for [curr-fn fn-defs]
`(~(second curr-fn) [~'event])
))
(deftype ~className []
~interface
~@(for [curr-fn fn-defs]
(rest curr-fn))
))
)
被叫:
(viewHandler Bar
(defn onFoo [this event] (println "ok-1"))
(defn onBar [this event] (println "ok-2"))
)
但是我仍然不能为java方法注释做类型提示。
答案 0 :(得分:1)
从简单的事情开始:
(defmacro looper [ifc & fn-names]
`(do
~@(for [curr-fn fn-names]
[curr-fn] )))
(println (macroexpand-1
'(looper IFC fun1 fun2 fun3)))
;=> (do [fun1] [fun2] [fun3])
反引号(反引号?)启动内联代码模板。 〜@关闭模板部分并开始实时代码执行(尝试用〜代替〜@来查看差异 - 一个额外的括号层)。
但是,我们要输出的代码更像(fun1 [] ...)
,这是我们不想要执行的文字代码。所以,这必须包含在另一个语法 - 引用/模板中,但我们需要另一个〜使“curr-fn”再次成为“实时代码”:
(defmacro looper2 [ifc & fn-defs]
`(do
(definterface ~ifc
~@(for [curr-fn fn-defs]
`(~(second curr-fn) [~'event] )))
(deftype ~ifc []
~@(for [curr-fn fn-defs]
`(IHandler ( ~@(rest curr-fn) [] ))))
))
(newline)
(pprint (macroexpand-1
'(looper2 MyController
(defn fun1 [this event] (println "ok-1"))
(defn fun2 [this event] (println "ok-2"))
)))
结果是:
(do
(clojure.core/definterface MyController
(fun1 [event])
(fun2 [event]))
(clojure.core/deftype
MyController
[]
(basic.t1/IHandler (fun1 [this event] (println "ok-1") []))
(basic.t1/IHandler (fun2 [this event] (println "ok-2") []))))
我们需要外(do ...)形式,因为我们输出(definterface ...)和(deftype ...)形式。
我会留给你找出类型提示等等。