2017-01-09 25 views
0

私は基本的な例でマクロを調べていますが、どのように動作するのか分かりません。Clojure:なぜこのマクロは動作しませんか?

この:

(defmacro evalf [f v] 
    (f v)) 
(evalf + 2) 

は動作しません。

は、私が試した:~~ @などが、彼らはどちらか動作しません:

(defmacro evalf [f v] 
    '(f v)) 
(evalf + 2) 

運...

は、私は他の構文を理解していません。私はシンボルfが+を指していないのを見ますが、私は "+の値fを取る"とは言いません。

あなたはそれをより明確にすることができますか?事前

答えて

4

です:

(defmacro evalf [f v] `(~f ~v)) 

または

どちらも同じことを行います。必要なs式を生成します。 この場合、(evalf + 10)はコンパイル時に(+ 10)に展開され、実行時に正常に評価されます。

2つ目はこれです:

(defmacro evalf [f v] ((resolve f) v)) 

今機能fは、コンパイル時にと呼ばれることになるので、マクロが結果に展開されます:(f v)10

あなたの変種は黙って失敗しました(evalf + 10)を呼び出すと ここで+は単なるシンボルであり、マクロの視点からの関数への参照ではないため、を呼び出しようとしますでは、clojureのシンボルに関数のセマンティクスがあるため、完全に正しい構文ですが、この呼び出しではnilが生成されます。 (シンボル呼び出しの例:('+ {'+ 10}) => 10)したがって、このシンボルという名前の関数を取得したい場合は、2番目の例のように、それを解決する必要があります。

そして'(f v)を有する変異体は、ちょうど2つのシンボルのリストに展開:'f'v、その後も第一の変形例のように、nilを返すランタイム呼び出し('f 'v)につながります。

+0

お返事ありがとうございますが、私はあなたのことをもっと理解しましたので、私はこれを選びました –

4

で おかげで、引数がフォーム(partial * 2)66など未評価の合格evalf

  • の呼び出しで

    (defmacro evalf [f v] 
        (list f v)) 
    
    (evalf (partial * 2) 66); 132 
    

    をお試しください。

  • マクロの本体は、の式(list '(partial * 2) '66)を生成します。マクロから返された、フォーム((partial * 2) 66)
  • に評価
    • は、132と評価します。

      まず1(あなたはおそらくしたい1):引用構文を使用して

代替は、2つのバリエーションがあり、あなたがやりたいん内容に応じて

(defmacro evalf [f v] 
    `(~f ~v)) 
関連する問題