3

私のマクロの理解は不完全なようです。引数をマクロに渡し、関数から呼び出すにはどうすればよいですか。コードの下の一見単純なコードは機能しません。

(defmacro bar [arg]
  (println (symbol? arg)))

(defn foo [arg]
  (bar arg))

(foo 'baz) => nil
4

3 に答える 3

6

foo を定義すると、マクロが評価されます。repl で foo 関数を定義すると、Clojure が true を出力することがわかります。

user=> (defmacro bar [arg]
         (println (symbol? arg)))
#'user/bar
user=> (defn foo [arg]
         (bar arg))
true ;  <= This is the print from your macro 
     ;     (it prints true, because arg is a symbol)
#'user/foo

マクロの本体を引用する必要があります。そうしないと評価され、戻り値が nil であるため、foo は単に nil を返します。

(defmacro bar [arg]
   `(println (symbol? ~arg)))
于 2013-03-16T12:14:44.243 に答える
4

マクロはコードを生成する必要があります。ソース式を引数として取り、新しいソースを作成します。

  1. マクロはどのソースを使用しますか?
  2. マクロはどのソースを生成しますか?

どれどれ:

user=> (defmacro bar [arg]
         (println (symbol? arg)))   
#'user/bar
user=> (bar 1)
false
nil
user=> (bar 'a)
false
nil
user=> (bar a)
true
nil

これは拡張です:

user=> (macroexpand-1 '(bar a))
true

有用なコードは生成されません。

于 2013-03-16T11:28:53.967 に答える
3

マクロが「機能する」ためには、通常はリスト式としてコードを返す必要があります。したがって、あなたの意図のために、以下を提供する必要があります。

(defmacro bar (arg)
  `(println (symbol? ,arg)))

(これは、リストを構築するための便利な表記法として quasiquote を使用します。) 使用するポイントでbar、defmacro コードを実行することにより、そのリストを作成するために拡張されます。その後、リストがコンパイルされます。たとえば、次のようになります。

(progn (bar 10))

に展開されます

(progn (println (symbol? 10))

これはコンパイルされ、後でコードを実行すると「nil」が出力されます。(bar a)' ' のエラーが発生することに注意してください。これは、おそらく oa 値を 使用a is not boundして展開が評価されるためです。戻ります。(println (symbol a))a(bar 'a)T

この正しいbarマクロを使用すると、関数fooはコンパイル時に次のように展開されます。

(defun foo (x)
  (println (symbol? x))

これは適切に計算(foo 'a)されます。(foo 10)

于 2013-03-16T16:13:45.400 に答える