用循环构建宏结果

时间:2015-06-10 19:59:26

标签: clojure javafx

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

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

1 个答案:

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

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