Как этот синтаксис обратной цитаты работает в lisp? - PullRequest
4 голосов
/ 04 июня 2019

Вот упрощенный пример из книги «О Лиспе» Пола Грэма (схема типа синтаксиса).

(define-macro (bar)
  (let ((x 10) (y '(1 2 3)) (z 'foo))
    `(list ,x `(,',z ,,@y))))

Я знаю, как ,,@y должен работать, но не уверен, как именно ,',z должен работать, что должно бытьоценивается первым и в каком порядке.(Я знаю, что он должен вычислять символ foo, потому что он возвращает (10 (foo 1 2 3)) в guile, но я не уверен, какие именно шаги).

Мне нужно это для моего lisp в JavaScript, где я получаю результат:

(10 ((unquote z) 1 2 3))

, потому что он просто оценивает форму слева направо (я только специально обрабатываю ,, и больше запятых).Как вы должны оценить это выражение.

В книге также есть такой пример:

(defmacro propmacro (propname)
   `(defmacro ,propname (obj)
       `(get ,obj ',',propname)))

как следует оценивать ',',?Какие шаги в этом случае?

Есть ли еще какие-нибудь странные крайние случаи с обратной / квазицитатой?Можете ли вы показать примеры тех и как они должны оцениваться и в каком порядке?

1 Ответ

6 голосов
/ 04 июня 2019

Как работает ,',z:

`(list ,x `(,',z ,,@y))))
          ^ ^
          |  `- this comma
           `- belongs to this backquote

Приведенная выше запятая интерполирует во внутреннюю кавычку выражение ',z или (quote ,z). А это ,z, в свою очередь, принадлежит внешней обратной цитате.

Таким образом, значение z вставляется в (quote ,z), чтобы сделать (quote <value-of-z>).

Тогда, фактически, внутренняя обратная цитата ведет себя как `(,'<value-of-z>).

Конкретно, предположим, что z содержит список (+ 2 2). Тогда мы можем понять это с точки зрения внешней обратной кавычки, вставляющей (+ 2 2) во внутреннюю, чтобы получить `(,'(+ 2 2) ...). Теперь это легко понять: когда внутренняя обратная кавычка оценивается, (+ 2 2) защищается от оценки, в результате чего получается объект ((+ 2 2) ...).

Шаблон ,',',', ... ,',expr используется для получения единственной оценки expr во время оценки самой внешней обратной цитаты, так что это значение затем распространяется через любое количество раундов оценки оставшихся вложений обратной цитаты, не подвергаясь дальнейшей оценке. Здесь действует своего рода «алгебра обратных цитат», в которой «запятые и кавычки отменяются».

Вы также можете визуализировать ,',','... как своего рода буровое долото, которое копается в слоях вложения, чтобы вы могли установить буквальное значение в любом месте структуры. Э.Г.

(defmacro super-nested-macro (arg)
  `(... `(.... `(.....`(we simply want arg down here ,',',',arg)))))

Автор super-nested-macro просто хочет вставить значение arg в шаблон, в положение, которое скрыто в трех других обратных кавычках. Таким образом, обычный ,arg не может быть использован: эта запятая будет неверно истолкована как принадлежащая самой внутренней обратной цитате.

Есть ли еще какие-нибудь странные крайние случаи с обратной / квази-цитатой?

Один странный крайний случай в обратном кавычке пытается слиться в точку:

`(a b c . ,@foo)  ;; not allowed

`(a b c . ,foo)   ;; OK: equivalent to `(a b c ,@foo)

Не уверен, как различные реализации работают с обратной кавычкой в ​​точечной позиции:

`(a b c . `(d e f))

Это на самом деле не имеет смысла, и я подозреваю, что фактический полученный результат будет зависеть от внутренних реализаций обратной цитаты.

Не все объекты просматриваются для цитирования:

 `#c(,(sin theta) ,(cos theta)) ;; Not required by ANSI CL, oops!

Это может работать через расширение реализации.

...