26

私は Clojure マクロについて学んでおり、コード例にはコンストラクト'~symbolorが含まれていることがあり~'symbolます。(quoteフォームが評価されないようにすること、および'バッククォートがさらに名前空間修飾を追加すること、および ~ によって引用されたフォームが評価されることを知っています。私の質問は: 評価を停止してから開始することがなぜ有用なのですか? ~'symbolとも'~symbol違うと思いますが、どうしてですか?

4

2 に答える 2

33

~'symbol非修飾シンボルを生成するために使用されます。Clojure のマクロはデフォルトで名前空間をキャプチャするため、マクロ内のシンボルは通常は に解決され(your-namespace/symbol)ます。unquote-quote イディオムは(symbol)、引用されたシンボルに評価されることにより、単純で修飾されていないシンボル名になります。Clojureの喜び より:

(defmacro awhen [expr & body]
  `(let [~'it ~expr] ; refer to the expression as "it" inside the body
    (when ~'it
      (do ~@body))))

(awhen [:a :b :c] (second it)) ; :b

'~symbolマクロなどに名前を挿入するために使用される可能性があります。ここでsymbolは、値にバインドされます - let [symbol 'my-symbol]。この値は、マクロが を評価して生成するコードに挿入されますsymbol

(defmacro def-symbol-print [sym]
  `(defn ~(symbol (str "print-" sym)) []
    (println '~sym))) ; print the symbol name passed to the macro

(def-symbol-print foo)
(print-foo) ; foo
于 2012-08-14T19:53:32.577 に答える
6

~関数のリーダーマクロですunquote。引用符で囲まれたリスト内では、リテラルシンボルとして使用されるのではなく、シンボルが評価されます。

user> (def unquoted 4)
user>`(this is an ~unquoted list)
(user/this user/is user/an 4 clojure.core/list)
user> 

引用符で囲まれていない記号を除くすべてが、引用符で囲まれていない記号が値4に解決された記号と同じように使用されました。これは、マクロの記述で最もよく使用されます。replは、結果のリストを出力するときに、名前の前に名前空間(ユーザー)も出力します。

多くのマクロは、基本的に、関数では実行できないものにわずかなバリエーションを加えるように設計された単なるテンプレートです。この不自然な例では、テンプレートマクロはdefへの呼び出しを生成することによって関数を定義します。引用符を外した構文引用符を使用すると、これがはるかに読みやすくなります。

user> (defmacro def-map-reducer [name mapper reducer] 
         `(defn ~name [& args#] 
              (reduce ~reducer (map ~mapper args#))))

#'user/def-map-reducer
user> (def-map-reducer add-incs inc +)
#'user/add-incs
user> (add-incs 1 2 3 4 5)
20

に比べ:

user> (defmacro def-map-reducer [name mapper reducer] 
          (let [args-name (gensym)] 
              (list `defn name [`& args-name] 
                   (list `reduce reducer (list `map mapper args-name)))))

#'user/def-map-reducer
user> (def-map-reducer add-decs dec +)
#'user/add-decs
user> (add-decs 1 2 3 4 5)
10
user> 

2番目の例では、構文引用符を使用していないため、auto-gensyms機能も使用していません。

于 2012-08-14T19:12:07.240 に答える