2011-01-05 17 views
2

この質問は、this answerという制限に基づいています。リテラルでないシーケンスの引用符を付けないでください

私はこのようなスプライシングにunquoteを使用するマクロがある場合:

(defmacro instantiate [klass values] 
     `(new ~klass [email protected])) 

valuesリテラルシーケンスまたは配列-ことができます場合にのみ動作します。

それはのようなシーケンスを保持VAR渡された場合:

(def v [1 2 3]) 
(macroexpand '(instantiate Person v)) 

を次に出力がvが順序ではないことを示すエラーになります。

でも関数呼び出しがリストとして解釈されます:

(defn vf [] [1 2 3]) 
(macroexpand '(instantiate Person (vf))) 
user=>(new Person vf) 

私の質問は:シーケンスはISN」スプライスされるこれらの2つのケースでClojureのマクロでスプライシングにunquoteを使用する方法はありますリテラルですか?

答えて

2

マクロは引数が評価されないため、表示される動作は意図した通りです。

マクロは、実行時ではなくコンパイル時に展開されます。マクロに渡された変数の値は、コンパイル時に利用できない可能性があります。したがって、一般的なケースではevalを使用するような汚いハックは機能しません。このようなトリックを必要とするマクロを作成しないでください。

+0

なる可能性が...あなたは、物事を昔ながらの方法を実行する必要があり、彼らは仕事をいけないときを除いて、ほとんどすべての場合に多くの時間を節約しますだから時にはそれは不可能で、他の時は悪い考えです。ありがとう。 –

1

スプライシング引用符は

(defmacro instantiate [klass values] 
    `(new ~klass [email protected])) 

(defmacro instantiate [klass values] 
    (concat (list 'new klass) (if (seq? values) 
            values 
            (list values)))) 

user=> (macroexpand '(instantiate asdf (1 2 3))) 
(new asdf 1 2 3) 

user=> (macroexpand '(instantiate asdf 1)) 
(new asdf 1) 
+0

パラメータの評価に関連しているので、私の実際の問題は解決しませんでしたが、実際にスプライシングクォートがどのように機能するかを理解できました。ありがとう –

関連する問題