Прежде чем перейти к некоторым вещам, для которых я хотел бы добавить еще один ответ, вот еще одно упоминание - часть, связанная с гомойконичностью, довольно коротка, но объяснение объясняет Рич Хикки!На 9 канале есть это прекрасное видео , в котором Рич Хики и Брайан Бекман рассказывают о Clojure.Понятно, что параллелизм является основным фокусом, но гомойконичность получает свой собственный (короткий) момент экранного времени, в течение которого Рич прекрасно объясняет взаимодействие между read
(функцией, которая преобразует конкретный синтаксис, записанный программистом, во внутреннее представлениеиз списков и т. д.) и eval
.У него есть эта хорошая диаграмма, показывающая, как eval
даже не знает, что код, который он оценивает, происходит от read
, работающего с текстовым файлом ... Артур уже объяснил суть этого, но эй, посмотрите это в любом случае, это оченьХорошее видео!
Отказ от ответственности: я буду упоминать Java и Python в качестве примеров под следующей горизонтальной полосой.Я хочу прояснить, что следующее - лишь грубый набросок того, почему я думаю, что может быть трудно создать гомо-логичный Java или Python с поддержкой макросов в стиле Lisp;это всего лишь академическое упражнение, и я не хочу рассматривать вопрос о том, есть ли какая-либо причина, чтобы попытаться в первую очередь.Кроме того, Я не хочу подразумевать, что синтаксис языка с макросами в стиле Лисп должен содержать явные разделители для древовидных структур ;Дилан (беспаренный Лисп?), По-видимому, дает контрпример.Наконец, я использую выражение Макросы в стиле Лиспа , потому что я изучаю только макросы в стиле Лисп.Например, в языке Forth есть другое средство макросов, которое я не очень понимаю, за исключением того, что я знаю, что оно позволяет создавать злой, классно выглядящий код.Очевидно, синтаксические расширения могут быть реализованы несколькими способами.Не обращая на это внимания ...
Я хотел бы ответить на вторую часть вашего вопроса - как получается, что большинство языков программирования не считаются гомойконичными?Мне придется затронуть семантику Лиспа в процессе, но поскольку Нильс уже предоставил ссылки на хорошие источники информации о самом термине «гомоиконический», а Артур описал цикл чтения -> макроразвертка -> как найденныйв Clojure я буду опираться на это в дальнейшем.Для начала позвольте мне процитировать отрывок из Алана Кея (взят из статьи в Википедии, которая также ссылается на первоисточник):
[...] Interactive LISP [...] иTRAC [...] оба "гомоичны" в том смысле, что их внутреннее и внешнее представления по сути одинаковы.
(Эти [...] биты скрывают много текста, но сутьбез изменений.)
Теперь давайте зададимся вопросом: каково внутреннее представление Java в Java? ... Ну, это даже не имеет смысла.Компилятор Java имеет определенное внутреннее представление Java, а именно абстрактное синтаксическое дерево;чтобы создать «гомо-звуковую Java», нам нужно было бы сделать это представление AST первоклассным объектом в Java и , чтобы разработать синтаксис, который позволял бы нам писать AST напрямую.Это может оказаться довольно сложным.
Python представляет пример негомоиконического языка, который интересен тем, что в настоящее время он поставляется с инструментарием AST-манипулирования в виде модуля ast
.В документах для этого модуля прямо указано, что Python AST могут меняться между выпусками, что может или не может быть обескураживающим;тем не менее, я полагаю, что трудолюбивый программист мог бы взять модуль ast
, разработать синтаксис (возможно, на основе S-выражений, может быть, на основе XML) для непосредственного описания AST Python и создать синтаксический анализатор для этого синтаксиса в обычном Python, используя ast
,тем самым сделав солидный первый шаг к созданию гомоиконического языка с семантикой Python.(Я полагаю, что я когда-то сталкивался с диалектом Lisp, компилируемым в байт-код Python ... Интересно, возможно, он что-то делает на каком-то уровне?)
Даже тогда остается проблема извлечения конкретных выгод из такого рода гомойконичности. Это рассматривается как полезное свойство членов семейства языков Lisp, потому что оно позволяет нам писать программы, которые пишут дополнительные программы, среди которых макросы являются наиболее заметными. Теперь, , хотя макросы активируются одним способом из-за того, что так легко манипулировать внутренним представлением кода на Лиспе в Лиспе, они также не менее важны для модели исполнения Лисп : Программа на Лиспе - это просто набор форм на Лиспе; они обрабатываются функцией Lisp eval
, которая отвечает за определение значений выражений и вызывает соответствующие побочные эффекты в нужное время; семантика Lisp - это в точности семантика eval
. Вопрос о том, как вещи работают внутренне, чтобы сохранить эту семантическую иллюзию, будучи достаточно быстрым, является деталью реализации; Лисп-система обязана предоставить функцию eval
программисту и действовать , как если бы Лисп-программы обрабатывались этой функцией.
В современных системах Lisp часть договора eval
заключается в том, что он выполняет дополнительную фазу предварительной обработки, во время которой макросы расширяются до оценки кода (или компиляции и запуска, в зависимости от обстоятельств). Это конкретное средство не является необходимой частью системы Lisp, но его так просто подключить к этой модели выполнения! Кроме того, мне интересно, не является ли это единственной моделью исполнения, которая делает управляемыми макропреобразования в Лиспе, что означало бы, что любой язык, стремящийся включить макросы в стиле Лисп, должен был бы принять подобную модель исполнения. Моя интуиция подсказывает мне, что это действительно так.
Конечно, как только язык записывается в нотации, непосредственно параллельной его AST, и использует Lisp-подобную модель исполнения с функцией / объектом-оценщиком, нужно задаться вопросом, не случайно ли это другой диалект Lisp ... даже если его синтаксис AST-параллелизма оказывается основанным на XML. Дрожь