В каком смысле такие языки, как Эликсир и Джулия homoiconic?

Гоконичность в Lisp легко видеть:

(+ 1 2)

- это вызов функции + с 1, 2 в качестве аргументов, а также список, содержащий +, 1 и 2. Это одновременно и код, и данные.

На языке, подобном Джулии, хотя:

1 + 2

Я знаю, что мы можем разобрать это в Expr в Джулии:

:(1 + 2)

И тогда мы сможем получить АСТ и манипулировать им:

julia> Meta.show_sexpr(:(1+2)) (:call, :+, 1, 2)

Итак, мы можем манипулировать программой AST в Julia (и Elixir). Но являются ли они homoiconic в том же смысле, что и Lisp - это какой-нибудь фрагмент кода, который действительно является только структурой данных в самом языке?

Я не вижу, как такой код, как 1 + 2 в Julia, сразу же похож на данные, как (+ 1 2) в Lisp является просто списком. Это все еще гомиконический, тогда?

Ответ 1

По словам Билла Клинтона, "это зависит от того, что означает значение слова" есть ". Ну, хорошо, не совсем, но это зависит от того, что означает слово" homoiconic ". Этот термин достаточно противоречивый, что мы уже не говорим, что Джулия гомокиновая - так что вы сами можете решить, соответствует ли она. Вместо того, чтобы пытаться определить гомоконичность, я процитирую, что Kent Pitman (кто-то знает что-то о Lisp) говорит в Интервью Slashdot в 2001 году:

Мне нравится Lisp готовность представлять себя. Люди часто объясняют это своей способностью представлять себя, но я думаю, что это неправильно. Большинство языков способны представлять себя, но у них просто нет желания. Программы Lisp представлены списками, и программисты знают об этом. Не имело бы значения, были ли это массивы. Неважно, какая структура программы представлена, а не синтаксис символов, но помимо этого выбор довольно произволен. Не важно, чтобы представление было выбором Right®. Просто важно, чтобы это был общий, согласованный выбор, чтобы существовало богатое сообщество программных программ, которые "торгуют" в этом общем представлении.

Он также не определяет гомоконичность - он, вероятно, не хочет больше входить в аргумент определения, чем я. Но он решает суть дела: насколько готов язык представлять себя? 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.

Это не просто поверхностное представление кода Юлии как структуры данных - так Джулия представляет свой код для себя. Когда вы вводите выражение в REPL, оно анализируется на объекты Expr. Те объекты Expr затем передаются в eval, что "опускает" их на несколько более регулярные объекты Expr, которые затем передаются на вывод типа, все реализованы в Джулии. Ключевым моментом является то, что компилятор использует то же самое представление кода, который вы видите. Ситуация не отличается от Lisp. Когда вы смотрите на код Lisp, вы фактически не видите объекты списка - они существуют только в памяти компьютера. То, что вы видите, представляет собой текстовое представление списковых литералов, которое интерпретирует интерпретатор Lisp и превращается в объекты списка, которые он затем анализирует, подобно Джулии. Синтаксис Julia можно рассматривать как текстовое представление для Expr литералов - Expr просто оказывается несколько менее общей структурой данных, чем список.

Я не знаю подробностей, но я подозреваю, что Elixir похож - может быть, Хосе зазвонит.

См. также: