Как далеко LISP макросы могут идти?
===================================

Я много читал, что LISP может переопределить синтаксис на лета, предположительно, с помощью макросов. Мне любопытно, как далеко это на самом деле идти? Вы можете переопределить структуру языка настолько, что она становится пограничным компилятором для другого языка? Например, вы могли бы изменить функциональный характер LISP в более объектно-ориентированного синтаксиса и семантики, может сказать, имеющий синтаксис ближе к чему-то вроде Ruby?

В частности, можно ли избавиться от скобки ад с помощью макросов? Я узнал достаточно (Emacs-) LISP для настройки Emacs с моими собственными микро-функциями, но я очень любопытно, как далеко макросы могут идти в настройках языка.

 

Это очень хороший вопрос.

Я думаю, что это нюансы, но, безусловно, отвечает:

Макросы не застряли в з-выражениях. См LOOP макроса для очень сложного языка, написанные с использованием ключевых слов (символов). Таким образом, в то время как вы можете начать и закончить цикл с круглыми скобками, внутри он имеет свой собственный синтаксис.

Пример:

```
(loop for x from 0 below 100
      when (even x)
      collect x)

```

Это, как говорится, самые простые макросы просто использовать S-выражения. И вы бы «застряли», используя их.

Но S-выражений, как Серджио ответил, начинают чувствовать. Синтаксис выходит из пути, и вы начинаете кодирования в синтаксическом дереве.

Что же касается читателя макросов, да, вы, вероятно, можете написать что-то вроде этого:

```
#R{
      ruby.code.goes.here
  }

```

Но вы должны были бы написать свой собственный синтаксис Ruby, синтаксический анализатор.

Вы также можете имитировать некоторые из Ruby, строит, как блоки, с помощью макросов, которые собирают с существующими конструкциями Lisp.

```
#B(some lisp (code goes here))

```

будет переводить

```
(lambda () (some lisp (code goes here)))

```

Смотрите [эту страницу](http://rottcodd.wordpress.com/2007/11/29/lambda-shortcut/) для того, как сделать это.

 

Да, вы можете переопределить синтаксис, чтобы Lisp становится компилятор. Вы делаете это с помощью «чтения макросов», которые отличаются от обычного «компилятора Макросы», что вы, вероятно, думаете.

Common Lisp имеет встроенный объект для определения нового синтаксиса для читателя и читатель макросов обработать этот синтаксис. Эта обработка осуществляется при считывании времени (который идет перед компиляцией или Eval времени). Чтобы узнать больше об определении читатель макросов в Common Lisp, см Common Lisp HyperSpec - вы хотите прочитать [гл. 2, "Синтаксис"](http://www.lispworks.com/documentation/HyperSpec/Body/02_.htm) и [Ch. 23, "Читатель"](http://www.lispworks.com/documentation/HyperSpec/Body/23_.htm) . (Я считаю , что схема имеет один и тот же объект, но я не знаком с ней - см [источников Scheme](http://arclanguage.org/install) для [языка программирования Arc](http://arclanguage.org) ).

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

```
;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
  (declare (ignore inchar))
  (read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)

(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )

;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )

```

Вы говорите , что Lisp {походит на (и что}, как а). Затем вы создаете функцию ( `lcurly-brace-reader`) , что читатель будет вызывать всякий раз , когда он видит {, и вы используете , `set-macro-character`чтобы назначить эту функцию к {. Тогда вы скажите , что Lisp (и), как [и] (то есть, не имеет смысла синтаксис).

Другие вещи , которые вы могли бы сделать , включают, например, [создание нового синтаксиса строки](http://www.weitz.de/cl-interpol/) или с помощью [и] вложить в-затруднительного обозначение и обрабатывать его в S-выражения.

Вы можете также пойти далеко за пределы этого, пересматривая весь синтаксис с собственных макросов символов , которые будут вызывать действия в читателя, так что небо действительно есть предел. Это лишь одна из причин , почему [Пол Грэм](http://www.paulgraham.com/icad.html) и [другие](http://gigamonkeys.com/book/introduction-why-lisp.html) твердят , что Lisp является хорошим языком , на котором написать компилятор.

 

Я не эксперт Лисп, черт, я даже не Lisp программиста, но после того, как немного поэкспериментировать с языком, я пришел к выводу, что через некоторое время скобка начинает становиться «невидимыми», и вы начинаете видеть код, вы хотите быть. Вы начинаете уделять больше внимания синтаксических конструкций, создаваемых с помощью з-exprs и макросов, и меньше в лексической форме текста списков и скобкой.

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

Вы не могли бы быть в состоянии полностью заменить язык и получить синтаксис «Руби», но это не нужно. Благодаря гибкости языка вы могли бы положить конец, имеющий диалекте, который чувствует, как вы следуете «Рубин стиль программирования», если вы хотите, что бы это означало бы для вас.

Я знаю, что это всего лишь эмпирическое наблюдение, но я думаю, что я был одним из тех лисповских просветительских моментов, когда я понял, что это.

 

Снова и снова, новички в Lisp хотят «избавиться от всех круглых скобок.» Она длится в течение нескольких недель. Ни один проект, чтобы построить серьезный синтаксис программирования общего назначения поверх обычного S-выражения парсер никогда не получает в любом месте, потому что программисты неизменно заводиться предпочитая то, что вы в настоящее время воспринимается как «скобка ад.» Это займет немного привыкнуть, но не так много! После того как вы привыкнете к нему, и вы можете реально оценить пластичность синтаксиса по умолчанию, восходящая к языкам, где есть только один способ выразить какую-либо конкретную программную конструкцию действительно решетка.

Это, как говорится, Lisp является отличным субстратом для построения Domain Specific Languages. Подобно тому, как хорошо, как, если не лучше, чем, XML.

Удачи!

 

Лучшее объяснение Lisp макросов я когда-либо видел это в

<https://www.youtube.com/watch?v=4NO83wZVT0A>

начиная примерно 55 минут. Это видео из разговора данного Питера Seibel, автор «Practical Common Lisp», который является лучшим Lisp учебника есть.

Мотивацией для Lisp макросов, как правило, трудно объяснить, потому что они действительно приходят в свои собственные в ситуациях, которые слишком длинны, чтобы представить в простой учебник. Питер приходит с большим примером; вы можете понять его полностью, и это делает хорошее, правильное использование Lisp макросов.

Вы спросили: «Вы могли бы изменить функциональный характер LISP в более объектно-ориентированного синтаксиса и семантики». Ответ: да. На самом деле, Lisp изначально не имеют каких-либо объектно-ориентированное программирование вообще, не удивительно, так как Lisp вокруг с пути, прежде чем объектно-ориентированного программирования! Но когда мы впервые узнали о ООП в 1978 году, мы смогли добавить его легко Лисп, используя, среди прочего, макросы. В конце концов, была разработана система Common Lisp Object (CLOS), очень мощный объектно-ориентированная система программирования, которая подходит элегантно в Лиспе. Все это может быть загружен как расширение - ничего не встроенный! Все это делается с помощью макросов.

Lisp имеет совершенно другую функцию, которая называется «читатель макросы», которые могут быть использованы для расширения поверхности синтаксиса языка. С помощью ридера макросов, вы можете сделать подъязыки, которые имеют C-подобный или Ruby, подобный синтаксис. Они превращают текст в Лиспе, внутренне. Они широко не используются большинство реального Лиспа программистов, в основном потому, что трудно расширить интерактивную среду разработки для понимания нового синтаксиса. Например, команды Emacs отступы будут сбиты с толку новым синтаксисом. Если вы энергичны, хотя, Emacs является расширяемым тоже, и вы могли бы научить его о своем новом лексическом синтаксисе.

 

Обычные макросы работают в списках объектов. Чаще всего, эти объекты являются другими списками (таким образом , образуя дерева) и символы, но они могут быть и другими объектами , такие как строки, хэш - таблицы, определяемого пользователем объекты и т.д. Эти структуры называют [S-EXPS](http://en.wikipedia.org/wiki/S-expression) .

Таким образом, при загрузке исходного файла, ваш Lisp компилятор будет анализировать текст и производить S-EXPS. Макросы работают на них. Это прекрасно работает, и это чудесный способ расширить язык в пределах духа втор-объединительные панели.

Кроме того, вышеупомянутый процесс анализа может быть расширена за счет «читателя макросов», которые позволяют настроить способ компилятор превращает текст в з-объединительные панели. Я полагаю, однако, что вы обнимаете синтаксис Lisp, вместо того чтобы сгибая ее в чем-то еще.

Звучит немного смущен , когда вы говорите «функциональную природу» в Lisp и «объектно-ориентированный синтаксис» в Ruby. Я не уверен , что «объектно-ориентированный синтаксис» , как предполагается, но Лисп является языком несколько парадигм и поддерживает объектно-ориентированное программирование *Extremelly* хорошо.

Кстати, когда я говорю , Lisp, я имею в виду [Common Lisp](http://en.wikipedia.org/wiki/Common_Lisp) .

Я предлагаю вам положить ваши предрассудки прочь и [дать лисповское честное идти](http://gigamonkeys.com/book/) .

 

То, что вы просите несколько как спрашивать, как стать экспертом шоколатье, так что вы можете удалить все, что адский коричневый материал из вашего любимого шоколадного торта.

 

Скобки ад? Я не вижу больше скобки в:

```
(function toto)

```

чем в:

```
function(toto);

```

И в

```
(if tata (toto)
  (titi)
  (tutu))

```

не более чем в:

```
if (tata)
  toto();
else
{
  titi();
  tutu();
}

```

Я вижу меньше скобки и «;» хоть.

 

Да, вы можете коренным образом изменить синтаксис, и даже избежать «круглых скобок в ад». Для этого вам нужно будет определить новый синтаксис для чтения. Посмотрите на читатель макросы.

Я подозреваю, однако, что для достижения уровня знаний Lisp для программирования таких макросов вам нужно будет погрузиться в языке до такой степени, что вы больше не будете рассматривать Parenthese «ад». Т.е. к тому времени, вы знаете, как избежать их, вы пришли, чтобы принять их как хорошую вещь.

 

посмотреть пример того, как читатель макросы могут расширить LISP читателя со сложными задачами, как XML шаблоны:

<http://common-lisp.net/project/cl-quasi-quote/present-class.html>

Этот **пользователь библиотеки** компилирует статические части XML в UTF-8 кодируются буквальным байтовых массивов во время компиляции, которые готовы к записи sequence'd в сетевой поток. и они могут использоваться в обычных LISP макросов, они ортогональны ... размещение символьных влияний запятой , какие части являются постоянными и которые должно быть оценено во время выполнения.

Более подробную информацию можно получить в: <http://common-lisp.net/project/cl-quasi-quote/>

другой проект , который для Common Lisp расширения синтаксиса: <http://common-lisp.net/project/cl-syntax-sugar/>

 

Если вы хотите сюсюкать выглядеть Руби использовать Ruby. 

Можно использовать Ruby (и Python) в очень LISP, как путь, который является одной из главных причин, они получили признание так быстро.

 

Одним из способов использования макросов, которые дули мой разум был во время компиляции проверки запросов SQL против БД.

После того, как вы понимаете, у вас есть полный язык под руку во время компиляции, он открывает новые интересные перспективы. Что также означает, что вы можете выстрелить себе в ногу в новых интересных способов (например, рендеринг компиляции не воспроизводимый, который может очень легко превратиться в кошмар отладки).

 

Это сложный вопрос. Так как шепелявость уже структурно так близко к дереву разбора разница между большим количеством макросов и реализациями собственной мини-языком в генераторе синтаксических анализаторов не очень понятная. Но, для открытия и закрытия Paren за исключением, вы можете очень легко в конечном итоге с чем-то, что не выглядит как лепет.

 

@sparkes

Иногда LISP является выбором понятного языка, а именно расширение Emacs. Я уверен, что я мог бы использовать Ruby, чтобы расширить Emacs, если я хотел, но Emacs был разработан, чтобы быть удлинен с LISP, так что, кажется, имеет смысл использовать его в этой ситуации.