什么是"符号"在朱莉娅?

时间:2014-05-05 19:58:18

标签: julia

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

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

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

除了: 我可以跑

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

我的两个项目符号仍然存在。

2 个答案:

答案 0 :(得分:176)

Julia中的符号与Lisp,Scheme或Ruby中的符号相同。但是,在我看来,the answers对这些相关问题are not really satisfactory。如果您阅读这些答案,似乎符号与字符串不同的原因是字符串是可变的,而符号是不可变的,符号也是“实习” - 无论这意味着什么。在Ruby和Lisp中,字符串确实是可变的,但它们不在Julia中,而这种区别实际上是一个红色的鲱鱼。符号被实现的事实 - 即通过快速相等比较的语言实现进行散列 - 也是一个无关的实现细节。你可以有一个没有实习符号的实现,而且语言也完全一样。

那么什么是符号呢?答案在于Julia和Lisp的共同点 - 能够将语言代码表示为语言本身的数据结构。有些人称之为"homoiconicity"Wikipedia),但其他人似乎并不认为只有一种语言能够同性化。但术语并不重要。关键是当一种语言可以代表自己的代码时,它需要一种方式来表示诸如赋值,函数调用,可以写成文字值的东西等等。它还需要一种方法来表示自己的变量。即,您需要一种方法来表示 - 作为数据 - 左侧的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绑定到字符串"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不是homoiconic:Ruby并没有将其表达式表示为Ruby对象。所以Ruby的符号类型是一种退化器官 - 一种遗留的改编,继承自Lisp,但不再用于其原始目的。 Ruby符号已被用于其他目的 - 作为哈希键,用于从方法表中提取方法 - 但Ruby中的符号不​​用于表示变量。

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

另见:

答案 1 :(得分:2)

参考目前的原始问题,即0.21版本(以及将来),DataFrames.jl允许将Symbol和字符串都用作列名,因为同时支持两者都没有问题并且在不同情况下,用户可能更喜欢Symbol或字符串。

这里是一个例子:

julia> using DataFrames

julia> df = DataFrame(:a => 1:2, :b => 3:4)
2×2 DataFrame
│ Row │ a     │ b     │
│     │ Int64 │ Int64 │
├─────┼───────┼───────┤
│ 1   │ 1     │ 3     │
│ 2   │ 2     │ 4     │

julia> DataFrame("a" => 1:2, "b" => 3:4) # this is the same
2×2 DataFrame
│ Row │ a     │ b     │
│     │ Int64 │ Int64 │
├─────┼───────┼───────┤
│ 1   │ 1     │ 3     │
│ 2   │ 2     │ 4     │

julia> df[:, :a]
2-element Array{Int64,1}:
 1
 2

julia> df[:, "a"] # this is the same
2-element Array{Int64,1}:
 1
 2