Подтвердить что ты не робот

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

Я новичок в Clojure, и я не уверен, что полностью понимаю разницу между апострофом и backtick в 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_ [email protected]> 5 5)
  • Исправьте меня, если я ошибаюсь, но мне кажется, что апостроф не позволяет всем символам (то есть + и х) переходить к их соответствующим параметрам var, тогда как backtick позволяет символам разрешать их var (но не оценивает к значениям в var). Это точно?
  • Что именно делает символ unquote (~) здесь? Является ли это eval'ing переменной var ее фактическому значению (т.е. Символ + для объекта функции и символ x для объекта числа)? Если бы вы могли объяснить это в терминах Clojure READ-COMPILE-EVAL, это также было бы полезно.
4b9b3361

Ответ 1

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

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

Наконец, вы можете исключить целую коллекцию связанных вещей.

 `(+ [email protected]`(x x))
 => (clojure.core/+ user/x user/x)

Посмотрите, что оба x es могли быть переданы как список символов, обозначенных как пространство имен, и были бы сплайсированы в другой список. Вы не можете использовать ~ или [email protected] вне коллекции с обратным отсчетом.

Ответ 2

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 (списки, массивы и т.д.).