2

The JoyofClojureのリスト13.3をよりよく理解しようとしています。これは、他のマクロを生成するマクロです(Clojure 1.4でプリミティブ配列関数が実装される方法とよく似ています)。

実行時に、生成されたマクロのサフィックスを出力するだけのマクロを作成したいと思います。すなわち

user=> (nested-macro joe)
user=> (nested-macro-named-joe)
hello from joe
nil

私はこの仕事をするのに苦労しています。

これが私が試したことです:

試行1

(defmacro nested-macro [name]
  `(defmacro ~(symbol (str "nested-macro-named-" name))
     []
     `(println "hello from " ~name)))

出力:

hello from #<core$name clojure.core$name@502c06b2>

試行2

(defmacro nested-macro [name]
  (let [local-name name]
    `(defmacro ~(symbol (str "my-custom-macro-named-" ~local-name))
       []
       `(println "hello from " ~local-name))))

エラー

IllegalStateException Attempting to call unbound fn: #'clojure.core/unquote clojure.lang.Var$Unbound.throwArity (Var.java:43)

試行3:

(defmacro nested-macro [name]
  (let [local-name name]
    `(defmacro ~(symbol (str "nested-macro-named-" name))
       []
       `(println "hello from " ~(symbol local-name)))))

コンパイラエラー:

CompilerException java.lang.RuntimeException: No such var: joy.dsl/local-name

念のために#、ローカル変数に追加してみましたが、上記と同様の結果が得られましたが、「自動」の名前が付けられています。たとえば、local-name__1127__auto__これがソリューションの一部であるとは思えません。

どうすればこれを機能させることができますか?

4

1 に答える 1

3

マクロの何が問題になっているのかを知るために、私はいつもを使用していますmacroexpand-1

最初の例から:

(macroexpand-1 '(nested-macro joe))

結果:

(clojure.core/defmacro nested-macro-named-joe [] 
  (clojure.core/seq 
    (clojure.core/concat 
      (clojure.core/list (quote clojure.core/println)) 
      (clojure.core/list "hello from ") 
      (clojure.core/list clojure.core/name))))

最後のパラメーターを見ると、clojure.core / nameを使用していることがわかります。これは、実際には「name」という名前のパラメーターが必要なため、おそらく必要なものではありません。

これを修正するには、パラメータに別の引用符を付けないでくださいname。ただし、名前paramは実際にはシンボルであるため、実際に必要なのは、次のように名前を取得することです。

(defmacro nested-macro [the-name]
  `(defmacro ~(symbol (str "nested-macro-named-" the-name))
     []
     `(println "hello from " ~~(name the-name))))
于 2012-09-24T22:10:14.023 に答える