別の名前空間から呼び出そうとしているマクロ生成マクロがあり、「存在しない修飾変数を参照できません」で失敗します。
問題を例示する最も単純な次のコードでそれを再現することができました。回避策も見つけましたが、問題の原因と、より良い解決策が存在するかどうかを理解したいと思います。
問題
ファイルfoo.clj
(ns foo)
(defmacro create-my-macro []
`(defmacro my-macro []
nil))
ファイルboo.clj
(ns boo (:use [foo]))
(create-my-macro)
上記のコードを次のコマンドで実行した場合:
java -cp clojure-1.4.0.jar clojure.main boo.clj
...で失敗します:
Exception in thread "main" java.lang.RuntimeException: Can't refer to qualified var that doesn't exist, compiling:(...boo.clj:2)
回避策
何らかの理由で、作成するマクロの名前をパラメーターとして受け入れるようにマクロ生成マクロを拡張しても、失敗はありません。
ファイルfoo.clj
(ns foo)
(defmacro create-my-macro [macroName]
(let [the-macroName (symbol macroName)]
`(defmacro ~the-macroName []
1)))
ファイルboo.clj
(ns boo (:use [foo]))
(create-my-macro "foo")
(println (foo))
上記のようにファイルboo.cljを実行すると、文句なしにコンソールにクリーンな「1」が出力されます。
では、最初のケースで何が問題だったのでしょうか。また、マクロを生成するマクロの名前をパラメーターとして受け入れるように変更して、それを修正する別の方法はありますか?また、macro-generated-macroが同じ名前空間から呼び出されたときに失敗しないのはなぜですか?