Как далеко могут зайти макросы LISP?[закрыто]

StackOverflow https://stackoverflow.com/questions/1988

  •  08-06-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

Я думаю, что это нюансировано, но определенно требует ответственности:

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

Пример:

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

При этом большинство простых макросов просто используют s-выражения.И вы бы "застряли", используя их.

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

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

#R{
      ruby.code.goes.here
  }

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

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

#B(some lisp (code goes here))

перевел бы на

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

Видишь эта страница о том, как это сделать.

Другие советы

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

Common Lisp имеет встроенное средство для определения нового синтаксиса для reader и макросов reader для обработки этого синтаксиса.Эта обработка выполняется во время чтения (которое предшествует времени компиляции или оценки).Чтобы узнать больше об определении макросов reader в Common Lisp, см. Common Lisp Hyperspec - вам захочется прочитать Гл.2, "Синтаксис" и Гл.23, "Читатель".(Я полагаю, что Scheme имеет ту же возможность, но я не так хорошо знаком с ней - см. Источники схемы для Язык программирования Arc).

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

;; { 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, что { похоже на a ( и что } похоже на a ).Затем вы создаете функцию (lcurly-brace-reader), который читатель будет вызывать всякий раз, когда увидит {, и вы используете set-macro-character чтобы назначить эту функцию {.Затем вы сообщаете Lisp, что ( и) похожи на [и] (то есть не имеют смысла в синтаксисе).

Другие вещи, которые вы могли бы сделать, включают, например, создание нового строкового синтаксиса или используя [ и ], чтобы вложить в фиксированную запись и обработать ее в S-выражения.

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

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

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

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

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

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

При этом Lisp является отличной основой для создания языков, специфичных для конкретной предметной области.Так же хорошо, как и XML, если не лучше.

Удачи вам!

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

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

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

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

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

В Lisp есть совершенно другая функция, называемая "макросы чтения", которая может быть использована для расширения поверхностного синтаксиса языка.Используя макросы Reader, вы можете создавать подъязыки с синтаксисом, подобным C или Ruby.Они внутренне преобразуют текст в Lisp.Они не используются широко большинством настоящих программистов на Lisp, главным образом потому, что трудно расширить интерактивную среду разработки для понимания нового синтаксиса.Например, команды отступов Emacs были бы сбиты с толку новым синтаксисом.Однако, если вы энергичны, Emacs тоже расширяем, и вы могли бы рассказать ему о своем новом лексическом синтаксисе.

Обычные макросы работают со списками объектов.Чаще всего этими объектами являются другие списки (образующие таким образом деревья) и символы, но они могут быть и другими объектами, такими как строки, хэш-таблицы, пользовательские объекты и т.д.Эти структуры называются s-exps.

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

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

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

Кстати, когда я говорю "Шепелявый", я имею в виду Обычный шепелявый.

Я предлагаю вам отбросить свои предрассудки и дайте Лиспу честный ход.

Ад в скобках?Я больше не вижу круглых скобок в:

(function toto)

чем в:

function(toto);

И в

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

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

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

Хотя я вижу меньше скобок и ';'.

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

Да, вы можете коренным образом изменить синтаксис и даже избежать "ада в скобках".Для этого вам нужно будет определить новый синтаксис reader.Загляните в макросы Reader.

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

Если вы хотите, чтобы lisp выглядел как Ruby, используйте Ruby.

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

смотрите этот пример того, как макросы reader могут расширить возможности программы чтения lisp с помощью сложных задач, таких как создание шаблонов XML:

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

это пользовательская библиотека компилирует статические части XML в литеральные массивы байтов в кодировке UTF-8 во время компиляции, которые готовы к последовательной записи в сетевой поток.и их можно использовать в обычных макросах lisp, они ортогональны...расположение символа запятой влияет на то, какие части являются постоянными, а какие должны быть оценены во время выполнения.

более подробная информация доступна по адресу: http://common-lisp.net/project/cl-quasi-quote/

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

@искры

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top