Elixir 和 Julia 之类的语言在什么意义上是谐音的? [英] In what sense are languages like Elixir and Julia homoiconic?

查看:17
本文介绍了Elixir 和 Julia 之类的语言在什么意义上是谐音的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Homoiconicity in Lisp is easy to see:

(+ 1 2)

既是对+的函数调用,以12为参数,又是一个包含+<的列表/code>、12.它同时是代码和数据.

is both the function call to + with 1, 2 as arguments, as well as being a list containing +, 1, and 2. It is simultaneously both code and data.

不过,在像 Julia 这样的语言中:

In a language like Julia, though:

1 + 2

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

I know we can parse this into an Expr in Julia:

:(1 + 2)

然后我们可以获取 AST 并对其进行操作:

And then we can get the AST and manipulate it:

朱莉娅>Meta.show_sexpr(:(1+2))(:call, :+, 1, 2)

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

So, we can manipulate a program's AST in Julia (and Elixir). But are they homoiconic in the same sense as Lisp- is any snippet of code really just a data structure in the language itself?

我看不出像 Julia 中的 1 + 2 这样的代码是如何立即成为数据的——就像 Lisp 中的 (+ 1 2) 只是一个列表.那还是谐音吗?

I don't see how code like 1 + 2 in Julia is, immediately, data- like how (+ 1 2) in Lisp is just a list. Is it still homiconic, then?

推荐答案

用比尔克林顿的话来说,这取决于‘是’这个词的含义是什么".好吧,好吧,不是真的,但这确实取决于同音"这个词的含义.这个词有足够的争议,我们不再说 Julia 是谐音的——所以你可以自己决定它是否符合条件.我不会试图定义同音性,而是引用 Kent Pitman (谁知道一两件事关于 Lisp)在 Slashdot 采访 早在 2001 年:

In the words of Bill Clinton, "It depends upon what the meaning of the word 'is' is". Well, ok, not really, but it does depend on what the meaning of the word "homoiconic" is. This term is sufficiently controversial that we no longer say that Julia is homoiconic – so you can decide for yourself whether it qualifies. Instead of trying to define homoiconicity, I'll quote what Kent Pitman (who knows a thing or two about Lisp) said in a Slashdot interview back in 2001:

我喜欢 Lisp 愿意代表自己.人们经常将此解释为它代表自己的能力,但我认为这是错误的.大多数语言都能够代表自己,但他们根本没有意愿.Lisp 程序由列表表示,程序员知道这一点.如果它是数组也没关系.重要的是它表示的是程序结构,而不是字符语法,但除此之外,选择是相当随意的.代表是正确的选择并不重要.重要的是它是一个共同的、商定的选择,这样才能有一个丰富的程序操纵程序社区在这种共同的表示中进行交易".

I like Lisp's willingness to represent itself. People often explain this as its ability to represent itself, but I think that's wrong. Most languages are capable of representing themselves, but they simply don't have the will to. Lisp programs are represented by lists and programmers are aware of that. It wouldn't matter if it had been arrays. It does matter that it's program structure that is represented, and not character syntax, but beyond that the choice is pretty arbitrary. It's not important that the representation be the Right® choice. It's just important that it be a common, agreed-upon choice so that there can be a rich community of program-manipulating programs that "do trade" in this common representation.

他也没有定义同音性——他可能比我更不想进入定义论证.但他切入了问题的核心:一种语言有多愿意代表自己?Lisp 非常愿意——你甚至无法避免它:程序作为数据的表示只是坐在那里,盯着你的脸.Julia 不使用 S-expression 语法,因此代码作为数据的表示不太明显,但它并没有隐藏得很深:

He doesn't define homoiconicity either – he probably doesn't want to get into a definitional argument any more than I do. But he cuts to the heart of the matter: how willing is a language to represent itself? Lisp is willing in the extreme – you can't even avoid it: the representation of the program as data is just sitting right there, staring you in the face. Julia doesn't use S-expression syntax, so the representation of code as data is less obvious, but it's not hidden very deep:

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 code is represented by the Expr type (and symbols and atoms), and while the correspondence between the surface syntax and the structure is less immediately obvious, it's still there. And more importantly, people know that code is simply data which can be generated and manipulated, so there is a "rich community of program-manipulating programs", as KMP put it.

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

This is not just a superficial presentation of Julia code as a data structure – this is how Julia represents its code to itself. When you enter an expression in the REPL, it is parsed into Expr objects. Those Expr objects are then passed to eval, which "lowers" them to somewhat more regular Expr objects, which are then passed to type inference, all implemented in Julia. The key point is that the compiler uses the exact the same representation of code that you see. The situation is not that different in Lisp. When you look at Lisp code, you don't actually see list objects – those only exist in the computer's memory. What you see is a textual representation of list literals, which the Lisp interpreter parses and turns into list objects which it then evals, just like Julia. Julia's syntax can be seen as a textual representation for Expr literals – the Expr just happens to be a somewhat less general data structure than a list.

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

I don't know the details, but I suspect that Elixir is similar – maybe José will chime in.

更新(2019 年)

在过去 4 年多的时间里,我对此进行了更多思考,我认为 Lisp 和 Julia 之间的主要区别在于:

Having thought about this more for the past 4+ years, I think the key difference between Lisp and Julia is this:

  • 在 Lisp 中,代码的语法与用于表示该代码的数据结构的语法相同.
  • 在 Julia 中,代码的语法与表示该代码的数据结构的语法完全不同.

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

Why does this matter? On the pro-Julia side, people like special syntax for things and often find S-expression syntax inconvenient or unpleasant. On the pro-Lisp side, it's much easier to figure out how to do metaprogramming correctly when the syntax of the data structure you're trying to generate (to represent code) is the same as the syntax of the code that you would normally write. This is why one of the best pieces of advice when people are trying to write macros in Julia is to do the following:

  1. 写一个您希望宏生成的代码类型的示例
  2. 在该代码上调用 Meta.@dump 以将其视为数据结构
  3. 编写代码以生成该数据结构 - 这是您的宏.

在 Lisp 中,您不必执行第 2 步,因为代码的语法已经与数据结构的语法相同.在 Julia 中有 quasiquoting(在 Lisp 中)quote ... end:(...) 构造,它们允许您使用代码语法构造数据结构,但这仍然不如让他们首先使用相同的语法那么直接.

In Lisp, you don't have to do step 2 because syntax for the code is already the same as the syntax for the data structure. There are the quasiquoting (in Lisp speak) quote ... end and :(...) constructs in Julia, which allow you to construct the data structures using code syntax, but that's still not as direct as having them use the same syntax in the first place.

另请参阅:

这篇关于Elixir 和 Julia 之类的语言在什么意义上是谐音的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆