Lisp 像Elixir和Julia这样的语言有什么意义?

Lisp 像Elixir和Julia这样的语言有什么意义?,lisp,julia,homoiconicity,Lisp,Julia,Homoiconicity,Lisp中的同源性很容易看出: (+12) 既是以1、2作为参数的对+的函数调用,也是包含+、1和2的列表。它同时是代码和数据 不过,用茱莉亚这样的语言: 1+2 我知道我们可以在Julia中将其解析为Expr: :(1+2) 然后我们可以得到AST并操纵它: julia>Meta.show\u sexpr(:(1+2)) (:call,:+,1,2) 因此,我们可以在Julia(和Elixir)中操纵程序的AST。但是,它们是否与Lisp具有相同的含义?任何代码片段是否真的只是语言本身的数据结

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

(+12)

既是以
1
2
作为参数的对
+
的函数调用,也是包含
+
1
2
的列表。它同时是代码和数据

不过,用茱莉亚这样的语言:

1+2

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

:(1+2)

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

julia>Meta.show\u sexpr(:(1+2))
(:call,:+,1,2)

因此,我们可以在Julia(和Elixir)中操纵程序的AST。但是,它们是否与Lisp具有相同的含义?任何代码片段是否真的只是语言本身的数据结构


我看不出Julia中的
1+2
这样的代码是如何立即成为数据的——Lisp中的
(+12)
只是一个列表。那么,这仍然是说教吗?

用比尔·克林顿的话说,“这取决于‘是’这个词的含义。”。好吧,不是真的,但这取决于“同象性”这个词的含义。这一术语极具争议性,我们不再说朱莉娅是同性恋——所以你可以自己决定它是否合格。我将引用(谁知道Lisp的一两件事)在2001年的一篇回忆录中所说的话,而不是试图定义同象性:

我喜欢Lisp表现自己的意愿。人们经常把这解释为它表现自身的能力,但我认为这是错误的。大多数语言都能表达自己,但他们根本没有表达自己的意愿。Lisp程序由列表表示,程序员知道这一点。如果它是数组也没关系。重要的是它所表示的是程序结构,而不是字符语法,但除此之外,选择是相当随意的。表示是否正确并不重要。重要的是,这是一个共同的、一致同意的选择,这样就可以有一个丰富的程序操作程序社区,在这个共同的表示中“做交易”

他也没有定义同象性——他可能和我一样不想卷入定义的争论。但他切入了问题的核心:一种语言有多愿意表现自己?Lisp非常愿意——你甚至无法避免它:程序作为数据的表示就在那里,盯着你的脸。Julia不使用S-expression语法,因此代码作为数据的表示形式不太明显,但隐藏的不是很深:

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)
Julia代码由
Expr
类型(以及符号和原子)表示,虽然表面语法和结构之间的对应关系不太明显,但它仍然存在。更重要的是,人们知道代码只是可以生成和操作的数据,所以正如KMP所说,有一个“丰富的程序操作程序社区”

这不仅仅是Julia代码作为数据结构的一种肤浅的表示——这就是Julia如何向自己表示其代码。在REPL中输入表达式时,它将被解析为
Expr
对象。然后,这些
Expr
对象被传递到
eval
,这会将它们“降低”到更规则的
Expr
对象,然后这些对象被传递到类型推断,所有这些都是实现的。关键的一点是,编译器使用与您看到的代码完全相同的表示形式。在Lisp中情况并没有那么不同。当您查看Lisp代码时,实际上并没有看到列表对象——它们只存在于计算机内存中。您看到的是列表文字的文本表示,Lisp解释器将其解析并转换为列表对象,然后对其求值,就像Julia一样。Julia的语法可以看作是
Expr
文本的文本表示形式,
Expr
恰好是一种比列表更不通用的数据结构

我不知道细节,但我怀疑长生不老药是类似的——也许何塞会插嘴

更新(2019)

在过去4年多的时间里,我一直在思考这个问题,我认为Lisp和Julia之间的关键区别在于:

  • 在Lisp中,代码的语法与用于表示该代码的数据结构的语法相同
  • 在Julia中,代码的语法与表示该代码的数据结构的语法完全不同
为什么这很重要?在支持Julia的方面,人们喜欢事物的特殊语法,并且经常发现S表达式语法不方便或令人不快。在pro-Lisp方面,当您试图生成(表示代码)的数据结构的语法与您通常编写的代码的语法相同时,更容易弄清楚如何正确地进行元编程。这就是为什么当人们试图在Julia中编写宏时,最好的建议之一是执行以下操作:

  • 编写一个示例,说明希望宏生成的代码类型
  • 对该代码调用
    Meta.@dump
    ,将其视为数据结构
  • 编写代码以生成该数据结构—这是您的宏
  • 在Lisp中,不必执行步骤2,因为代码的语法已经与数据结构的语法相同。有准语言(在Lisp语言中)
    quote。。。end
    :(…)
    在Julia中构造,允许您使用代码语法构造数据结构,但这仍然不如让它们首先使用相同的语法直接

    另请参见:


    你可能有兴趣知道,至少朱莉娅不再声称自己是同性恋。主要原因是它定义不清,所以声称