По словам Билла Клинтона, «это зависит от значения слова« есть »». Ну да ладно, не совсем, но это зависит от значения слова «гомоиконный». Этот термин достаточно противоречивый, поэтому мы больше не говорим, что Джулия гомиконична, поэтому вы можете сами решить, подходит ли он. Вместо того, чтобы пытаться определить гомоаконичность, я процитирую то, что Кент Питман (кто кое-что знает о Лиспе) сказано в Интервью со Slashdot в 2001 году:
Мне нравится готовность Lisp представлять себя. Люди часто объясняют это его способностью представлять себя, но я думаю, что это неправильно. Большинство языков способны представлять себя, но у них просто нет желания. Программы на Лиспе представлены списками, и программисты это знают. Неважно, если бы это были массивы. Важно то, что представлена структура программы, а не синтаксис символов, но помимо этого выбор довольно произвольный. Не важно, чтобы это представление было правильным® выбором. Просто важно, чтобы это был общий, согласованный выбор, чтобы могло появиться богатое сообщество программ, управляющих программами, которые «торгуют» в этом общем представлении.
Он также не определяет гомоиконность - он, вероятно, не хочет вдаваться в аргумент об определении больше, чем я. Но он затрагивает самую суть вопроса: насколько язык готов сам себя представлять? Lisp готов в высшей степени - вы даже не можете этого избежать: представление программы в виде данных просто сидит прямо здесь, глядя вам в глаза. Джулия не использует синтаксис S-выражений, поэтому представление кода в виде данных менее очевидно, но не очень глубоко:
julia> ex = :(2a + b + 1)
:(2a + b + 1)
julia> dump(ex)
Expr
head: Symbol call
args: Array(Any,(4,))
1: Symbol +
2: Expr
head: Symbol call
args: Array(Any,(3,))
1: Symbol *
2: Int64 2
3: Symbol a
typ: Any
3: Symbol b
4: Int64 1
typ: Any
julia> Meta.show_sexpr(ex)
(:call, :+, (:call, :*, 2, :a), :b, 1)
julia> ex.args[3]
:b
julia> ex.args[3] = :(3b)
:(3b)
julia> ex
:(2a + 3b + 1)
Код Джулии представлен типом Expr
(а также символами и атомами), и хотя соответствие между синтаксисом поверхности и структурой не так очевидно, оно все еще существует. И что еще более важно, люди знают, что код - это просто данные, которые можно сгенерировать и которыми можно манипулировать, поэтому существует «богатое сообщество программ, управляющих программами», как выразился KMP.
Это не просто поверхностное представление кода Julia как структуры данных - это то, как Julia представляет свой код самой себе. Когда вы вводите выражение в REPL, оно разбирается на Expr
объектов. Эти Expr
объекты затем передаются в eval
, который «понижает» их до несколько более обычных Expr
объектов, которые затем передаются в вывод типа, все реализовано в Юлии. Ключевым моментом является то, что компилятор использует то же самое представление кода, которое вы видите. В Лиспе ситуация не такая уж иная. Когда вы смотрите на код Lisp, вы на самом деле не видите объектов списка - они существуют только в памяти компьютера. Вы видите текстовое представление литералов списков, которые интерпретатор Лиспа разбирает и превращает в объекты списков, которые затем оценивает, как и Джулия. Синтаксис Джулии можно рассматривать как текстовое представление Expr
литералов - Expr
просто оказывается несколько менее общей структурой данных, чем список.
Я не знаю подробностей, но подозреваю, что Elixir похож - может быть, Хосе вмешается.
Обновление (2019 г.)
Подумав об этом больше в течение последних 4+ лет, я думаю, что ключевое различие между Lisp и Julia заключается в следующем:
- В Лиспе синтаксис кода такой же, как синтаксис структуры данных, которая используется для представления этого кода.
- В Julia синтаксис кода сильно отличается от синтаксиса структуры данных, представляющей этот код.
Почему это важно? Сторонники Юлии любят особый синтаксис для вещей и часто находят синтаксис S-выражений неудобным или неприятным. На стороне pro-Lisp гораздо проще понять, как правильно выполнять метапрограммирование, когда синтаксис структуры данных, которую вы пытаетесь сгенерировать (для представления кода), совпадает с синтаксисом кода, который вы обычно пишете . Вот почему один из лучших советов, когда люди пытаются писать макросы на Julia, - это сделать следующее:
- Напишите пример кода, который должен генерировать ваш макрос.
- Вызовите
Meta.@dump
этого кода, чтобы увидеть его как структуру данных.
- Напишите код для создания этой структуры данных - это ваш макрос.
В Lisp вам не нужно делать шаг 2, потому что синтаксис кода уже такой же, как синтаксис структуры данных. В Julia есть квазицитатные (на языке Lisp) конструкции quote ... end
и :(...)
, которые позволяют создавать структуры данных с использованием синтаксиса кода, но это все еще не так просто, как если бы они изначально использовали тот же синтаксис.
См. также:
person
StefanKarpinski
schedule
30.07.2015