小编典典

Julia 中的“符号”是什么?

all

具体来说:我正在尝试使用 Julia 的 DataFrames 包,特别是带有 names 选项的 readtable() 函数,但这需要一个符号向量。

  • 什么是符号?
  • 他们为什么会选择它而不是字符串向量?

到目前为止,我在 Julia 语言中只发现了少数几个对符号这个词的引用。似乎符号由“:var”表示,但我还不清楚它们是什么。

旁白:我可以跑

df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] )

我的两个项目符号问题仍然有效。


阅读 82

收藏
2022-08-05

共1个答案

小编典典

Julia 中的符号与 Lisp、Scheme 或 Ruby
中的符号相同。但是,在我看来,这些相关问题的答案并不令人满意。如果您阅读这些答案,似乎符号与字符串不同的原因是字符串是可变的,而符号是不可变的,并且符号也是“interned”——无论这意味着什么。字符串在
Ruby 和 Lisp 中确实是可变的,但它们在 Julia 中不是,这种差异实际上是一个红鲱鱼。符号被拘禁的事实 -
撀爄.e。由用于快速相等比较的语言实现散列 - 也是一个不相关的实现细节。您可以有一个不实习符号的实现,并且语言将完全相同。

那么什么是符号,真的吗?答案在于 Julia 和 Lisp
的共同点——将语言代码表示为语言本身的数据结构的能力。有些人称其为“同音性”(维基百科),但其他人似乎并不认为仅此一项就足以使语言成为同音。但术语并不重要。关键是,当一种语言可以表示它自己的代码时,它需要一种方法来表示诸如赋值、函数调用、可以写为文字值的东西等。它还需要一种方法来表示它自己的变量。即,您需要一种方法来表示“撀联盟数据”foo的左侧:

foo == "foo"

现在我们进入问题的核心:符号和字符串之间的区别在于foo该比较左侧和"foo"右侧之间的区别。左边是一个标识符,它的计算结果是绑定到当前范围内foo的变量的值。foo右边"foo"是一个字符串文字,它的计算结果为字符串值“foo”。Lisp
和 Julia 中的一个符号就是将变量表示为数据的方式。一个字符串只代表它自己。您可以通过应用它们来查看差异eval

julia> eval(:foo)
ERROR: foo not defined

julia> foo = "hello"
"hello"

julia> eval(:foo)
"hello"

julia> eval("foo")
"foo"

符号:foo计算的结果取决于“任何东西”的“撀爄”变量foo绑定到什么,而"foo"总是只计算为“foo”。如果您想在 Julia
中构造使用变量的表达式,那么您正在使用符号(无论您是否知道)。例如:

julia> ex = :(foo = "bar")
:(foo = "bar")

julia> dump(ex)
Expr
  head: Symbol =
  args: Array{Any}((2,))
    1: Symbol foo
    2: String "bar"
  typ: Any

除其他外,倾倒的东西显示的是,:foo您通过引用代码获得的表达式对象内部有一个符号对象foo = "bar":foo这是另一个示例,使用存储在变量中的符号构造表达式sym

julia> sym = :foo
:foo

julia> eval(sym)
"hello"

julia> ex = :($sym = "bar"; 1 + 2)
:(begin
        foo = "bar"
        1 + 2
    end)

julia> eval(ex)
3

julia> foo
"bar"

如果您尝试在sym绑定到 string时执行此操作"foo",它将不起作用:

julia> sym = "foo"
"foo"

julia> ex = :($sym = "bar"; 1 + 2)
:(begin
        "foo" = "bar"
        1 + 2
    end)

julia> eval(ex)
ERROR: syntax: invalid assignment location ""foo""

很清楚为什么这行不通——如果你尝试"foo" = "bar"手动分配,它也行不通。

这就是符号的本质:在元编程中,符号用于表示变量。当然,一旦您将符号作为数据类型,就很想将它们用于其他用途,例如用作哈希键。但这是对具有另一个主要目的的数据类型的偶然、机会主义使用。

请注意,我不久前不再谈论 Ruby。那是因为 Ruby 不是同音符号:Ruby 并不将其表达式表示为 Ruby 对象。所以 Ruby
的符号类型是一种退化器官——撀翼的剩余改编,继承自 Lisp,但不再用于其最初的目的。Ruby
符号已被用于其他目的——作为散列键,将方法从方法表中提取出来——Ruby 中的符号不​​用于表示变量。

至于为什么在 DataFrames 中使用符号而不是字符串,这是因为在 DataFrames
中将列值绑定到用户提供的表达式中的变量是一种常见的模式。所以列名是符号是很自然的,因为符号正是你用来将变量表示为数据的东西。目前,您必须写入df[:foo]才能访问该foo列,但在将来,您也许可以改为访问它df.foo。当这成为可能时,只有名称是有效标识符的列才能使用这种方便的语法访问。

2022-08-05