В Лиспе код - это данные.Какую пользу это дает? - PullRequest
24 голосов
/ 29 апреля 2011

В Лиспе код любой программы на самом деле является допустимой структурой данных. Например, это добавляет один и два вместе, но это также список из трех элементов.

(+ 1 2)

Какую пользу это дает? Что это позволяет вам делать, что невозможно и / или менее элегантно на других языках?

Ответы [ 4 ]

18 голосов
/ 29 апреля 2011

Чтобы прояснить ситуацию с представлением кода, учтите, что в каждый код языка - это данные: все, что вам нужно, это строки. (И, возможно, несколько файловых операций.) Размышление о том, как это поможет вам имитировать преимущества Lisp от наличия макросистем, является хорошим способом для просветления. Еще лучше, если вы попытаетесь реализовать такую ​​макросистему. Вы столкнетесь с преимуществами наличия структурированного представления по сравнению с плоскостностью строк, необходимостью сначала выполнить преобразования и определить «синтаксические хуки», чтобы указать, где их применять и т. Д. И т. Д.

Но главное, что вы увидите во всем этом, - это то, что макросы - это, по сути, удобное средство для зацепки компилятора - зацепки с недавно созданными ключевыми словами. Таким образом, единственное, что действительно необходимо, - это способ взаимодействия пользовательского кода с кодом компилятора. Плоские строки - один из способов сделать это, но они предоставляют настолько мало информации, что программе записи макросов остается задача реализации синтаксического анализатора с нуля. С другой стороны, вы можете представить некоторую внутреннюю структуру компилятора, например предварительно проанализированные AST-деревья, но они, как правило, предоставляют слишком много информации для удобства и , это означает, что компилятор должен каким-то образом иметь возможность анализировать новое синтаксическое расширение, которое вы намереваетесь реализовать. S-выражения - хорошее решение для последнего: компилятор может анализировать все что угодно, поскольку синтаксис одинаков. Они также являются решением первой проблемы, поскольку представляют собой простые структуры с широкой поддержкой языка для их разделения и повторного объединения по-новому.

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

8 голосов
/ 29 апреля 2011

Мой любимый пример ... В колледже некоторые мои друзья писали компилятор на Лиспе.Таким образом, все их структуры данных, включая дерево разбора, были s-выражениями lisp.Когда пришло время реализовать фазу генерации кода, они просто выполнили свое дерево разбора.

3 голосов
/ 29 апреля 2011

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

Если вы хотите выполнять вычисления с программами (создавать новые программы, компилировать программы в машинный код, переводить программы из Lisp на другие языки), у вас есть в основномтри варианта:

  • использовать строки.Это приводит к утомительным разбору и разбору строк все время.

  • использовать деревья разбора.Полезно, но становится сложным.

  • используйте символические выражения, как в Лиспе.Программы разбиты на знакомые структуры данных (списки, символы, строки, числа и т. Д.), А процедуры манипуляции написаны на обычном языке с предоставленной функциональностью.

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

2 голосов
/ 29 апреля 2011

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

(define-syntax and
  (syntax-rules ()
   ((and) #t)
   ((and thing) thing)
   ((and thing rest ...) (if thing (and rest ...) #f))))

Обратите внимание, что вызовы макросов просто сопоставляются с предложениями (and), (and thing) и (and thing rest ...) (в зависимости от арности вызова) и обрабатываются

В других языках макросам придется иметь дело с неким внутренним AST преобразуемого кода - иначе не было бы простого способа «увидеть» ваш код в программном формате.--- и это увеличило бы трения написания макросов.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...