使用循环构建宏结果

Build macro result with loops

我正在构建一个应该这样调用的宏:

(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 文件的控制器的手动构建实现已经在工作了,我只是想用一个宏来简化它,但我找不到任何关于如何做这种事情的帮助of 宏定义中的循环。


更新

宏快完成了,已经运行成功了。

(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 方法注释提供类型提示。

从简单的事情开始:

(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 [] ...),这是我们不想 想要执行的文字代码。所以,它必须被包裹在另一个 syntax-quote/template 中,但我们需要另一个 ~ 来使 "curr-fn" 再次成为 "live code":

(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 ...) 形式。

我会留给你找出类型提示等。