Ответ 1
Я не думаю, что есть эквивалент синтаксиса-кавычки функции quote
.
Читатель Clojure (в настоящее время) написан на Java. Класс SyntaxQuoteReader
в src/jvm/clojure/lang/LispReader.java
в источнике Clojure - это, вероятно, то, что вы хотите прочитать. Это кажется довольно сложным. Вы можете видеть, что там строятся списки, например (seq (concat ...))
.
ret = RT.list(SEQ, RT.cons(CONCAT, sqExpandList(seq)));
Обычно читателю не нужно возвращать простой код Clojure, а делать то, что нужно прямо на Java-земле. Например, '[1 2 3]
не дает код Clojure (vector 1 2 3)
. Может быть, так или иначе, но это не так. Читатель просто создает и возвращает сам векторный объект.
Аналогично, SyntaxQuoteReader
делает некоторую магию в Java немедленно для разрешения пространств имен символов и создания самих gensyms и возвращает некоторый искаженный и сложный вид кода Clojure, который делает правильные вещи, но не всегда легко для человека читать. Так ли это, потому что это должно быть, или потому, что это проще сделать на Java, или для производительности, или по какой-то другой причине, я не знаю. Аналогично, я не знаю, может ли quasiquote
существовать как простой макрос/специальная форма в Clojure и не существует, или вообще не может существовать. Я не понимаю, почему это не могло быть.
WrappingReader
в том же файле находится класс, который обрабатывает '
(обычный старый quote
). Вы можете видеть, что он просто переносит все, что вы передаете, в список, содержащий символ quote
плюс ваш аргумент. Это намного проще. Обратите внимание, что этот класс также обрабатывает @
, так что '@foo
возвращает (deref foo)
.
Этот поток может пролить немного света.
Изменить
Здесь макрос макросов quasiquote
. Обратите внимание, что этот код опирается и нарушает внутреннюю структуру Clojure ужасным образом. Пожалуйста, не используйте это ни для чего.
user> (defmacro quasiquote [x]
(let [m (.getDeclaredMethod clojure.lang.LispReader$SyntaxQuoteReader
"syntaxQuote"
(into-array [Object]))]
(.setAccessible m true)
(.invoke m nil (into-array [x]))))
#'user/quasiquote
user> (let [x 123] `(x 'x ~x))
(user/x (quote user/x) 123)
user> (let [x 123] (quasiquote (x 'x ~x)))
(user/x (quote user/x) 123)