Что означает "квази" в квази-цитатах?
Некоторые языки, такие как Haskell (или Nemerle), имеют квази-цитаты. Интересно, что означает "квази" и существуют ли также "цитаты" без "квази"?
5 ответов
Я считаю, что это понятие пришло из языков Лисп.
Программа, написанная на Лиспе, состоит из серии списков списков списков и т. Д., Например:
(defn f [x y] (+ x y))
Из-за такой однородности можно представлять и манипулировать таким кодом в качестве данных, поэтому приведенная выше последовательность символов интерпретируется как буквальный список. Это очень полезная особенность Лиспса, одна из их отличительных особенностей. Для удобства языки Lisp позволяют "заключать в кавычки" значимые последовательности, превращая их из определений и выражений в списки. Это выглядит так:
'(defn f [x y] (+ x y))
В данном случае это буквальный список, напрямую доступный для деструктуризации с использованием аналогов Haskell's head
а также tail
и другие методы. Таким образом, "цитата" означает "сделать буквальное значение из списка".
Однако манипулировать списками напрямую с head
- а также tail
-подобные функции. Это становится заметным, когда вы начинаете писать сложные макросы или даже макросы, генерирующие макросы. Таким образом, здесь идет "квази-цитата", буквально "почти цитата". Обычно квазиквотация выглядит как простая цитата (но с другим символом кавычки):
`(defn f [x y] (+ x y))
Но это гораздо более мощная вещь. В квазицитированном списке вы можете заменить произвольные элементы их действительными значениями из внешней области видимости, получая что-то вроде шаблонов. Пример:
(let [z 10] `(defn f [x y] (+ x y ~z)))
Здесь мы имеем обязательную ценность 10
в z
переменная, а затем мы подставляем его в квазицитатуру. Это выражение дает
'(defn f [x y] (+ x y 10))
Это простой пример; Языки Лисп позволяют делать много других полезных вещей с квазицитатами.
Это понятие перенесено в другие языки, которые поддерживают манипуляции с синтаксическими деревьями. Например, средством Haskell здесь является Template Haskell, и он полностью поддерживает квази-цитату, то есть создает шаблоны и заполняет их значениями из внешней области видимости. В языках со сложным синтаксисом (таких как Haskell) квази- и простые цитаты становятся едва ли не единственным разумным способом манипулирования синтаксическими деревьями.
UPD: хм, кажется, что в Haskell это более сложная функция, чем простая замена. Квазицитат в Haskell выглядит как произвольный преобразователь и вычислитель выражений, которые могут быть определены пользователем.
Эти понятия существуют в языке Lisp и его вариантах.
На этих языках каждый раз, когда переводчик видит список (a b c ... z)
оценивает это, применяя a
к другим элементам b ... z
,
Если вы хотите, чтобы список не оценивался (и, следовательно, интерпретировался как список), вы должны заключить его в кавычки. Например, '(a b c)
оценивается как список с тремя элементами, а не как a
применительно к b
а такжеc
, Вы можете увидеть цитату какостановку оценки.
Теперь квази-цитата ведет себя как цитата, за исключением того, что вы можете возобновить оценку внутри частей списка. Вы квазицитируете с обратным апострофом `и разрешаете неквотировать некоторые подвыражения оператором запятой (по крайней мере, в Scheme, я не знаю о других вариантах Lisp). Например
`(a ,(b c))
оценивает список с двумя элементами: a
и результат оценки (b c)
,
Это особенно полезно для создания шаблонов, где вы заполняете дыры, не заключая в кавычки. Пример (взят оттуда):
(define (create-shipping-employee-association name)
`((name ,name)
(employee-id-no ,(get-next-employee-id!))
(department shipping)
(hire-date ,(get-day) ,(get-month) ,(get-year))))
В Nemerle квази-цитата является ( http://nemerle.org/metaprogramming.pdf):
"
Метаязык - это язык для программирования таких операций. Обычно он имеет собственный синтаксис для описания различных конструкций языка объекта.
Например, в нашей системе:
<[ 1 + f (2 * x) ]>
обозначает синтаксическое дерево выражения:
1 + f (2 * x)
Эта идея называется квази-цитата.
Префикс квази происходит из-за возможности вставки значений выражений метаязыка в цитируемый контекст.
если g(y)
это такое выражение, мы можем написать:
<[ 1 + $(g(y)) ]>
который описывает синтаксическое дерево, чья вторая часть заменяется результатом оценки g(y)
"
Квази в основном означает, что вы можете поместить знак доллара в кавычку и снова переключиться на код без кавычек:
<[ WriteLine( $(ReadLine()) ) ]>
Это выведет во время выполнения строку, введенную во время компиляции (на самом деле я не думаю, что это будет работать, например, в Visual Studio, поскольку ReadLine требует ввода с консоли, но вы можете читать из файлов, сети и т. Д.).
Цитата - это просто строковый литерал. Квази- кавычки "заключаются в кавычки" в том смысле, что они представляют ввод в некотором смысле, а не являются скомпилированным кодом; они просто представляют его в форме, которой легче манипулировать изнутри процесса компиляции (абстрактное синтаксическое дерево, которое вы можете использовать различными способами, что несколько безопаснее, чем работа с текстом).