在什么意义上,像Elixir和Julia homoiconic这样的语言?

use*_*425 36 lisp homoiconicity julia

Lisp中的同质性很容易看出:

(+ 1 2)

既是函数调用+1,2作为参数,以及作为含有一个列表+,12.它同时是代码和数据.

但是,像朱莉娅这样的语言:

1 + 2

我知道我们可以Expr在Julia中将其解析为:

:(1 + 2)

然后我们可以获得AST并操纵它:

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

因此,我们可以在Julia(和Elixir)中操纵程序的AST.但它们是否与Lisp一样具有同音性 - 任何代码片段实际上只是语言本身的数据结构吗?

我不知道1 + 2Julia中的代码是如何立即像(+ 1 2)Lisp中的数据一样只是一个列表.它仍然是杀人的吗?

Ste*_*ski 47

比尔克林顿的话说,"这取决于'是'的含义是什么".嗯,好吧,不是真的,但它确实取决于"homoiconic"这个词的含义是什么.这个术语充满争议,我们不再说朱莉娅是同性恋的 - 所以你可以自己决定它是否合格.我不会试图定义同质性,而是引用肯特·皮特曼(谁知道关于Lisp的一两件事)在2001年的Slashdot采访中说:

我喜欢Lisp表达自己的意愿.人们经常将其解释为表现自己的能力,但我认为这是错误的.大多数语言都能够代表自己,但他们根本没有意愿.Lisp程序由列表表示,程序员知道这一点.如果它是阵列就没关系.重要的是它的程序结构是代表的,而不是字符语法,但除此之外,选择是非常随意的.表示是Right®的选择并不重要.重要的是,它是一个共同的,商定的选择,以便可以有一个丰富的程序操作程序社区,在这个共同的代表中"做交易".

他也没有定义同音性 - 他可能不想进入定义论证而不是我.但他切入了问题的核心:一种语言能够表达自己的意愿吗?Lisp愿意走极端 - 你甚至无法避免它:作为数据的程序表示只是坐在那里,盯着你看.Julia不使用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)
Run Code Online (Sandbox Code Playgroud)

Julia代码由Expr类型(和符号和原子)表示,虽然表面语法和结构之间的对应关系不那么明显,但它仍然存在.更重要的是,人们知道代码只是可以生成和操作的数据,因此有一个"丰富的程序操作程序社区",正如KMP所说的那样.

这不仅仅是Julia代码作为数据结构的表面呈现 - 这就是Julia如何将代码表示给自己.在REPL中输入表达式时,会将其解析为Expr对象.Expr然后传递这些对象eval,将它们"降低"为更常规的Expr对象,然后传递给类型推断,所有对象都在Julia中实现.关键是编译器使用与您看到的完全相同的代码表示.Lisp的情况并没有那么不同.当你查看Lisp代码时,实际上并没有看到列表对象 - 那些只存在于计算机内存中的列表对象.你看到的是列表文字的文本表示,Lisp解释器解析并转化为列表对象,然后它就像朱莉娅一样.Julia的语法可以看作文字的文本表示Expr- Expr恰好是一个比列表更不通用的数据结构.

我不知道细节,但我怀疑Elixir是相似的 - 也许José会插话.

也可以看看:

  • 我不确定这是否有区别 - 尽管语法很少,但是仍然需要解析S-exprs,所以Lisp REPL实际上也是一个PEPL.我认为主要区别在于`Expr`类型不是一般类型 - 它特定于代表代码. (7认同)
  • 因此,它更多是一个PEPL,而不是REPL。由于它不像Lisp一样读取数据表达式,而是将程序表达式解析为expr类型的专用数据。 (3认同)
  • 区别在于Lisp中的编程语言解析不是在文本输入的READ中完成的,而在Lisp数据结构的EVAL中则略有不同。EVAL可能不会将Lisp数据转换为表达式数据结构-无需执行该步骤即可实现评估器。 (2认同)
  • 列表只是列表。没有关于arg是什么,数据是什么,定义是什么,调用是什么,绑定是什么,函数是什么等的编码。Lisp列表对Lisp语法一无所知。READ以s表达式格式读取任何数据,并且对Lisp语法具有“零”知识。 (2认同)