Каковы практические различия между специальными формами и макросами? - PullRequest
19 голосов
/ 22 февраля 2012

Есть ли практические различия между специальными формами и макросами? Чем они отличаются?

Ответы [ 5 ]

19 голосов
/ 22 февраля 2012

Термины не совсем синонимы, но они также не являются исключительными (этот ответ предполагает Схему):

  • A специальная форма (также известная как синтаксис в отчетах схемы) - это выражение, которое не оценивается в соответствии с правилом по умолчанию для приложения функции. (Правило по умолчанию, просто чтобы быть явным, это eval все подвыражения, а затем apply результат первого в список результатов других.)
  • Система макросов - это языковая функция, которая позволяет определять новые специальные формы внутри самого языка. A macro - это специальная форма, определенная с помощью системы макросов.

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

Теперь важно отметить, что большинство специальных форм Scheme можно определить как макросы из действительно небольшого ядра примитивов: lambda, if и макросов. Минимальная реализация Scheme, которая обеспечивает только это, может все еще реализовывать как макросы; В недавних отчетах о схемах это различие проводится путем ссылки на такие специальные формы, как «синтаксис библиотеки», который можно определить в терминах макросов. На практике, однако, практические системы Scheme часто реализуют более богатый набор форм в качестве примитивов.

Семантически говоря, единственное, что имеет значение в выражении, это то, какое правило используется для его оценки, а не то, как это правило реализовано. Поэтому в этом смысле не важно, реализована ли специальная форма в виде макроса или примитива. Но, с другой стороны, детали реализации системы Scheme часто «просачиваются», так что вы можете позаботиться об этом ...

11 голосов
/ 22 февраля 2012

Lisp имеет определенные языковые примитивы, которые составляют формы Lisp:

  • литеральные данные : числа, строки, структуры, ...
  • вызовы функций , например (sin 2.1) или ((lambda (a b) (+ a b 2)) 3 4)
  • специальные операторы используются в специальных формах. Это примитивные встроенные языковые элементы. См. Специальные операторы в Common Lisp. Они должны быть реализованы в интерпретаторе и компиляторе. Common Lisp не предоставляет разработчику возможности вводить новых специальных операторов или предоставлять свои собственные версии этих операторов. Инструмент разбора кода должен понимать эти специальные операторы; в сообществе Lisp эти инструменты обычно называются «обходчиками кода». Во время определения стандарта Common Lisp было удостоверено, что это число очень мало и что все расширения в противном случае выполняются с помощью новых функций и новых макросов.
  • макросы : макросы - это функции, которые преобразуют исходный код. Преобразование будет происходить рекурсивно, пока в исходном коде не останется макросов. Common Lisp имеет встроенные макросы и позволяет пользователю писать новые.

Итак, самое важное практическое различие между специальными формами и макросами заключается в следующем: специальные операторы имеют встроенный синтаксис и семантику. Они не могут быть написаны разработчиком. Макросы могут быть написаны разработчиком.

4 голосов
/ 22 февраля 2012

Для меня наиболее практичным отличием является отладчик: макросы не отображаются в отладчике; вместо этого (обычно) неясный код из макроса раскрывается в отладчике. Отладка такого кода - это настоящая боль и хорошая причина убедиться, что ваши макросы надежны, прежде чем вы начнете полагаться на них.

4 голосов
/ 22 февраля 2012

В отличие от специальных форм, макроформы могут быть расширены макросом:

CL-USER(1): (macroexpand '(with-slots (x y z)
                              foo
                            (format t "~&X = ~A" x)))

(LET ((#:G925 FOO))
  (DECLARE (IGNORABLE #:G925))
  (DECLARE (SB-PCL::%VARIABLE-REBINDING #:G925 FOO))
  #:G925
  (SYMBOL-MACROLET ((X (SLOT-VALUE #:G925 'X))
                    (Y (SLOT-VALUE #:G925 'Y))
                    (Z (SLOT-VALUE #:G925 'Z)))
    (FORMAT T "~&X = ~A" X)))
T
2 голосов
/ 22 февраля 2012

супер короткий ответ для ленивых

Вы можете написать свои собственные макросы в любое время, хотя вы не можете добавлять специальные формы без перекомпиляции clojure,

...