40

Некоторые языки, такие как Haskell (или Nemerle), имеют quasiquotations. Интересно, что означает «квази», а также существуют «цитаты» без «квази».В чем смысл «квази» в квазикобратах?

+4

'quasi' просто латинский для 'как будто'. Не совсем уверен в остальном интересующем вас вопросе, +1. – ChristopheD

ответ

40

Я считаю, что это понятие происходит от языков Лиспа.

Программа написана в Лиспе состоит из серии списков списков списков и т.д., как это:

(defn f [x y] (+ x y)) 

Из-за такого единообразия можно представлять и манипулировать такой код, как данные, так что последовательность символов выше, интерпретируется как литеральный список. Это очень полезная функция Lisps, одна из их отличительных особенностей. Для удобства Lisp-языки позволяют «цитировать» значимые последовательности, превращая их из определений и выражений в списки. Это выглядит следующим образом:

'(defn f [x y] (+ x y)) 

В этом случае буквальный список, непосредственно для уничтожения того, используя аналоги head и tail и других методов в Haskell. Итак, «quote» означает «сделать буквальное значение из списка».

Однако управление списками нецелесообразно с помощью head - и tail-подобных функций. Он становится заметным, когда вы начинаете писать сложные макросы или даже макрогенерирующие макросы. Итак, здесь происходит «квазивокация», буквально «почти цитата». Обычно quasiquotation выглядит как простой цитаты (но с другим символом цитирую):

`(defn f [x y] (+ x y)) 

Но это гораздо более мощная вещь. В квазикоматовом списке вы можете заменить произвольные элементы своими действительными значениями из внешней области, в основном получая что-то вроде шаблонов. Пример:

(let [z 10] `(defn f [x y] (+ x y ~z))) 

Здесь мы связывание значение 10 к z переменное, а затем мы подставляя его внутрь quasiquote. Это выражение дает

'(defn f [x y] (+ x y 10)) 

Это простой пример; Языки Lisp позволяют делать много других полезных вещей с квазикварталами.

Это понятие перенесено на другие языки, поддерживающие манипуляции с деревьями синтаксиса. Например, объект Haskell здесь Template Haskell, и он полностью поддерживает квазикотирование, т. Е. Создает шаблоны и заполняет их значениями из внешней области. В языках со сложным синтаксисом (например, Haskell) квази- и простые цитаты становятся почти единственным разумным способом манипулирования деревьями синтаксиса.

UPD: Хмм, кажется, что в Haskell это более сложная функция, чем простая замена. Quasiquote в Haskell выглядит как произвольный трансформатор и оценщик выражений, который может быть определен пользователем.

+7

Сначала он появился (я верю) на языках программирования в Lisp, но идея исходит от Quine (который также представил для них квадратную скобку), чтобы позволить однозначный способ ссылаться на то, что представляет символ, а не на сам символ. –

+0

Связано с обновлением ... вы говорите о: '(hola ~ (+ 1 2)) -> (hola 3)? – jneira

+0

@jneira. Нет, я имел в виду, что квазикотация Хаскелла позволяет определить пользовательские типы данных, к которым будет разрешаться квазиквартал (продолжающийся пример lisp, хотя и несколько надуманный, который будет векторами вместо списков) и определить пользовательские стратегии синтаксического анализа. В OP-ссылке на Haskell Wiki есть пример. Таким образом, можно использовать функцию квазикотации, чтобы генерировать произвольные деревья синтаксиса, а не только Haskell. –

2

Цитата - это просто строковый литерал. Quasi цитаты «цитируются» в том смысле, что они представляют вход в некотором смысле, а не как скомпилированный код; они просто представляют его в форме, которую легче манипулировать изнутри процесса компиляции (абстрактное синтаксическое дерево, которое можно трансформировать различными способами, которые несколько безопаснее, чем работа с текстом).

19

Эти понятия существуют на языке Лиспа и его вариантах.

В этих языках, когда интерпретатор видит список (a b c ... z), он оценивает его, применяя a к другим элементам b ... z.

Если вы хотите, чтобы список не был оценен (и, следовательно, он должен быть интерпретирован как список), вы должны указать quote it. Например, '(a b c) оценивает как список с тремя элементами, а не как a, применяемый к b и c. Вы можете увидеть цитату как , останавливая оценку.

Теперь квазивокация ведет себя как цитата, за исключением того, что вы можете возобновить оценку внутри частей списка. Вы quasiquote с обратным апострофом `и вы позволяете некоторым подвыражениям быть неуказанным с оператором запятой (по крайней мере, на Схеме, я не знаю о других вариантах Лиспа). Например

`(a ,(b c)) 

вычисляется в виде списка с двумя элементами: a, и результат оценки (b c).

Это особенно полезно для создания шаблонов, где вы заполняете отверстия, не заполняя их. Пример (взят из there):

(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)))) 
5

В Nemerle квази-цитата (http://nemerle.org/metaprogramming.pdf):

"

Мета-язык является языком для программирования таких операций Она обычно имеет свой. собственный синтаксис для описания различных конструкций объектного языка.

Например, в нашей системе:

<[ 1 + f (2 * x) ]> 

обозначает синтаксическое дерево выражения:

1 + f (2 * x) 

Эта идея называется квази-цитаты.

Префикс quasi проистекает из возможности вставки значений выражений метаязыков в цитируемый контекст.

, если g(y) такое выражение, можно записать:

<[ 1 + $(g(y)) ]> 

который описывает синтаксическое дерево, у которого вторая часть заменяется результатом оценки g(y)

"

2

Квази в основном означает, что вы можете поместить знак доллара внутри котировки и снова переключиться на код без котировки:

<[ WriteLine($(ReadLine())) ]> 

Это будет выводить во время выполнения строку, введенную во время компиляции (на самом деле я не думаю, что это сработает e. г.в Visual Studio, поскольку ReadLine требует ввода консоли; но вы можете читать файлы, сеть и т. д.).

+0

ОП стремился к значению этимологии, а не к коду. –