私のマクロの理解は不完全なようです。引数をマクロに渡し、関数から呼び出すにはどうすればよいですか。コードの下の一見単純なコードは機能しません。
(defmacro bar [arg]
(println (symbol? arg)))
(defn foo [arg]
(bar arg))
(foo 'baz) => nil
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)))
マクロはコードを生成する必要があります。ソース式を引数として取り、新しいソースを作成します。
どれどれ:
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
有用なコードは生成されません。
マクロが「機能する」ためには、通常はリスト式としてコードを返す必要があります。したがって、あなたの意図のために、以下を提供する必要があります。
(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)