私たちのclojureモジュールのバグを見つけながら、誰かが引数を渡した構文引用符付きマクロを見つけました。いくつかのデバッグの後、私は、引数が必要な値を持たないため、これが意図したとおりに動作しないことに気付きました。構文引用符付きマクロに引数を渡します
以下は、実際のコードで発生する状況の最小限の表現です。これはかなりよくポイントを説明する必要があります。
(def testargs {:arg1 "foo"
:arg2 "bar"})
(defmacro argtest
[arg1 arg2]
`(str [email protected](arg1 testargs) " " [email protected](arg2 testargs))
を予想通り、私はこのようなコードを呼び出す場合、これはうまく動作します:二つの引数を変数として渡された場合
(argtest :arg1 :arg2)
=> "foo bar"
しかし、それはしていませんとてもうまく機能:
(let [arg1 :arg1 arg2 :arg2]
(argtest arg1 arg2))
=> " "
問題の底に取得するには、私は次のようにマクロを変更して、再度テストを実行しました:
(defmacro argtest2
[arg1 arg2]
(str arg1 " " arg2))
(argtest2 :arg1 :arg2)
=> ":arg1 :arg2"
(let [argument1 :arg1 argument2 :arg2]
(argtest2 argument1 argument2))
=> "argument1 argument2"
ご覧のとおり、変数がの値として渡されます。どうすればこれを避けることができますか?私はマクロを避けるためにコードを書き直そうとするべきですか、どういうわけか私はこの作業をすることができますか?
明白な解決策は、当然のことながら、このようなものになるだろう:
(defmacro argtest
[arg1 arg2]
`(str (~arg1 ~testargs) " " (~arg2 ~testargs)))
しかし、マクロの出力を評価する前に、別のコードブロックに挿入されているので、これは不可能です。
:多分私はあなたの問題をoversimplifyingてるのに広い文脈またはあなたが何をしようとして知らなくても、最も簡単な解決策は、あなたがすべてのケースで評価の引数をしたいように見えるよう、機能を使用することです'〜testargs' - >' testargs'はうまくいくはずですか? – cfrick
(1)関数にマクロに変更できる場合は、それを行います。 (2)そうでない場合は、cfrickが '〜@ 'の代わりに'〜 'を使って言ったことをします。これは、あなたが示したものからは不要です。 –
@cfrick:はい、ここに投稿したもので動作しますが、生成されたコードはあとで例外をスローし始めるスレッディングマクロに挿入されます... – UncleBob