5

コンパイル時に複数のJavaクラスを生成するために使用されるclojureマクロを作成しようとしています。マクロの外部でgen-classを呼び出すと、クラスにアノテーションを追加できることがわかりました。ただし、マクロ内でgen-classを使用しようとすると、コンパイルされたクラスにアノテーションがありません。

私は自分の問題をこの例に要約しました:

(gen-class
  :name ^{Deprecated true} Test1
  :prefix Test1-
  :methods [[^{Deprecated true} getValue [] Integer]])

(defn Test1-getValue [] 42)

(defmacro create-test-class [name x]
  (let [prefix (str name "-")]
    `(do
      (gen-class
         :name ~(with-meta name {Deprecated true})
         :prefix ~(symbol prefix)
         :methods [[~(with-meta 'getValue {Deprecated true}) [] Integer]])
      (defn ~(symbol (str prefix "getValue")) [] ~x))))

(create-test-class Test2 56)

このファイルをコンパイルすると、Test1.classとTest2.classが作成されます。Eclipseで両方を調べたところ、Test1にはクラスレベルとメソッドレベルの両方の@Deprecatedアノテーションがありますが、Test2.classにはアノテーションがありません。macroexpandを使用すると、Test2.classに注釈を付ける必要があるように見えます。

user=> (set! *print-meta* true)
true
user=> (macroexpand '(create-test-class Test2 56))
(do (clojure.core/gen-class :name ^{java.lang.Deprecated true} Test2 :prefix Test2- :methods [[^{java.lang.Deprecated true} getValue [] java.lang.Integer]]) (user/defn Test2-getValue [] 56)) 

私はここで何が間違っているのですか?

4

1 に答える 1

4

Meikel Brandmeyerは、ここで質問に答えました。

https://groups.google.com/forum/#!topic/clojure/Ee1bVwcUT-c

「マクロ内の注釈を引用します。(メタ名 `{Deprecated true}を使用)。バックティックに注意してください。"

動作するマクロは次のとおりです。

(defmacro create-test-class [name x]
  (let [prefix (str name "-")]
    `(do
      (gen-class
         :name ~(with-meta name `{Deprecated true})
         :prefix ~(symbol prefix)
         :methods [[~(with-meta 'getValue `{Deprecated true}) [] Integer]])
      (defn ~(symbol (str prefix "getValue")) [] ~x))))
于 2013-02-28T14:44:52.167 に答える