web-dev-qa-db-ja.com

Clojure-'(アポストロフィ)と `(バッククォート)の違い

私はClojureにかなり慣れていないので、Clojureのアポストロフィとバックティックの違いを完全に理解しているかどうかはわかりません。

(def x 5)

;; Question 1
(+ x x)  ;; evaluates to 10
'(+ x x) ;; evaluates to (+ x x)
`(+ x x) ;; evaluates to (clojure.core/+ user/x user/x)

;; Question 2
`(~+ ~x ~x) ;; evaluates to (#<core$_PLUS_ clojure.core$_PLUS_@32ee28a9> 5 5)
  1. 私が間違っている場合は訂正してください。ただし、アポストロフィはすべてのシンボル(つまり、+とx)がそれぞれの変数に解決されるのを防ぎますが、バッククォートはシンボルをそれぞれの変数に解決することを許可します(ただし、値には評価されません) var内)。これは正確ですか?
  2. 引用符で囲まれていない記号(〜)はここで正確に何をしますか? varを実際の値に評価していますか(つまり、+記号は関数オブジェクトに、x記号は数値オブジェクトに)? ClojureのREAD-COMPILE-EVALフェーズの観点からこれを説明できれば、それも役に立ちます。
36
wmock

コレクションを'で引用すると、シンボル名は入力したとおりに引用されます。

'(+ x x) 
=> (+ x x)
(map namespace *1)
=> (nil nil nil)
'(bingo/+ lara/y user/z)
=> (bingo/+ lara/y user/z)
(map namespace *1)
=> ("bingo" "lara" "user")

バッククォートを使用してコレクションを引用すると、各シンボルの名前空間が検索されます。見つからない場合は、現在の名前空間を使用します。名前空間を指定すると、修飾された名前空間を使用した'と同じように機能します。

`(+ x x)
= > (clojure.core/+ user/x user/x)
(map namespace *1)
=> ("clojure.core" "user" "user")

~内で`を使用している場合、フォームは単純に引用符で囲まれません。これは、マクロが定義されている名前空間のシンボルと、マクロが使用されている名前空間のシンボルを使用するマクロを作成する場合に役立ちます。

 `(+ ~'x x)
 => (clojure.core/+ x user/x)
 `(+ ~x x)
 => (clojure.core/+ 3 user/x)

最後に、引用されたもののスプライシングのコレクション全体を引用解除できます。

 `(+ ~@`(x x))
 => (clojure.core/+ user/x user/x)

両方のxesが名前空間で修飾されたシンボルのリストとして渡され、別のリストにスプライスされた可能性があることを確認してください。アクサングラーブのコレクションの外で~または~@を使用することはできません。

33
Leon Grapenthin

BackquoteはClojure用語での構文引用です。 http://clojure.org/reader でその説明を参照してください。

読み取り中に、 `(〜+ 〜x〜x)は、字句環境を参照できるリストを生成するフォームに展開されます。次に、コンパイラはこのコードをコンパイルします。 `(〜+ 〜x〜x)が何に展開されるかを見てみましょう。その前に、引用符を付けます。

user=> '`(~+ ~x ~x)
(clojure.core/seq (clojure.core/concat (clojure.core/list +) (clojure.core/list x) (clojure.core/list x)))

`(〜+ 〜x〜x)の代わりにこのフォームをテキストエディタに挿入すると、+関数と2つのxを含むリストが作成されます。したがって、 `(〜+ 〜x〜x)は、特定の構造のリストを作成するClojureコードに展開されます。

バッククォートは、Clojureデータ(リスト、配列など)の一種のテンプレート言語です。

2
monoid