repl で動作するマクロがあり、次のように の外側let
と内側のコードで動作するlet
ようです。しかし、それも壊れており、その理由はわかりません。マクロは基本的に、呼び出す関数として最初の引数を取り、into-array
引数の最後のセットの前に配置し、最後の非コレクション引数のクラスをパラメーターとして配列に追加します (Java クラスにある場合)。階層。
(defmacro jvar [method & args]
(let [lastargs (last args)
evaled-lastargs (eval lastargs)]
(if (coll? evaled-lastargs)
(let [firstargs (butlast args)
klass (eval (last firstargs))
supset (map #(supers (class %)) evaled-lastargs)
common (apply intersection #{klass} supset)]
(if (seq common)
`(~method ~@(butlast firstargs) (into-array ~(first common) ~lastargs))
`(~method ~@firstargs (into-array ~lastargs))))
(throw (Error. "Last argument must be defn.")))))
使用法: Repl:
jfxcircles.core> (macroexpand '(jvar Group. Node [(Circle. 100)]))
(new Group (clojure.core/into-array javafx.scene.Node [(Circle. 100)]))
jfxcircles.core> (jvar Group. Node [(Circle. 100)])
#<Group Group@c26729e>
でlet
:
(let [root (Group.)
scene (Scene. root 800 600) ;etc. this is for JavaFX
...
circ (Circle. 100)
inner-group1 (jvar Group. [(Circle. 100)]) ; works
inner-group2 (jvar Group. [circ]) ; Instantiation Exception
inner-group3 (jvar Group. [(Rectangle. 100 100)]) ; works
inner-group4 (jvar Group. [(Rectangle. (.getWidth scene) 100)]) ; Instantiation exception
)
したがって、基本的には、そうでなければ同じであるはずの特定の状況下ではコンパイルされません。コンパイルされないため、マクロ展開を行うことができません。何か案は?
ありがとう