Clojure - разница между ' (апостроф) и ` (backtick)

Я довольно новичок в 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) в их соответствующие переменные, тогда как обратный тик позволяет символам разрешать их переменные (но не оценивает значения в пределах вар). Это точно?
  2. Что именно символ кавычки (~) делает здесь? Вычисляет ли переменная var ее фактическое значение (т. Е. Символ + для объекта функции и символ x для объекта числа)? Если бы вы могли объяснить это в терминах этапов READ-COMPILE-EVAL Clojure, это также было бы полезно.

2 ответа

Решение

Когда вы цитируете коллекцию с 'имя символа будет заключено в кавычки в том виде, в котором вы его вводите.

'(+ 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)

Смотрите оба xОни могли бы быть переданы как список символов, определенных в пространстве имен, и были бы объединены в другой список. Вы не можете использовать ~ или же ~@ за пределами цитируемой обратным следом коллекции.

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), она создаст список с функцией + и двумя x. Итак, `(~+ ~x ~x) расширяется до кода Clojure, который создает список определенной структуры.

Backquote является своего рода языком шаблонов для данных Clojure (списки, массивы и т. Д.).

Другие вопросы по тегам