Julia “a”是什么;符号「;朱莉娅?

Julia “a”是什么;符号「;朱莉娅?,julia,Julia,具体而言: 我试图使用Julia的DataFrames包,特别是带有names选项的readtable()函数,但这需要符号向量 什么是符号 为什么他们会选择它而不是字符串向量 到目前为止,我在茱莉亚语言中只找到了少数提到符号这个词的地方。似乎符号是用“:var”表示的,但我还不清楚它们是什么 旁白: 我能跑 df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] ) 我的两个带项目符号的问题仍然有效。Ju

具体而言: 我试图使用Julia的DataFrames包,特别是带有names选项的readtable()函数,但这需要符号向量

  • 什么是符号
  • 为什么他们会选择它而不是字符串向量
到目前为止,我在茱莉亚语言中只找到了少数提到符号这个词的地方。似乎符号是用“:var”表示的,但我还不清楚它们是什么

旁白: 我能跑

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

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

Julia中的符号与Lisp、Scheme或Ruby中的符号相同。然而,在我看来,对于那些相关的问题。如果你读了这些答案,似乎符号与字符串不同的原因是字符串是可变的,而符号是不可变的,符号也是“内部的”——不管这意味着什么。在Ruby和Lisp中,字符串确实是可变的,但在Julia中它们不是可变的,而这种差异实际上是在转移注意力。符号被插入的事实——即,由语言实现进行散列以进行快速相等比较——也是一个不相关的实现细节。你可以有一个不使用符号的实现,语言也完全一样

那么什么是符号呢?答案在于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=“bar”
得到的表达式对象内部有一个
:foo
符号对象。下面是另一个示例,使用存储在变量
sym
中的符号
:foo
构造表达式:

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不是同形图标:Ruby不将其表达式表示为Ruby对象。所以Ruby的符号类型是一种退化器官——一种从Lisp继承下来的遗留改编,但不再用于其原始用途。Ruby符号被用于其他目的——作为散列键,从方法表中提取方法——但Ruby中的符号不用于表示变量

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

另请参见:


关于到目前为止的原始问题,即0.21版本(以及将来的版本)DataFrames.jl允许将
Symbol
s和字符串用作列名,因为支持两者都不是问题,在不同的情况下,用户可能会首选
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

关于这个主题的一些对话可以在这里找到:Interning:在计算机科学中,字符串Interning是一种只存储每个不同字符串值的一个副本的方法,它必须是不可变的。插入字符串使某些字符串处理任务更节省时间或空间,但在创建或插入字符串时需要更多时间。在一个点上你写
eval(:foo)
,在另一个点上你写
eval(sym)
eval(:foo)
eval(foo)
之间是否存在有意义的区别?非常重要的是:
eval(:foo)
给出变量
foo
绑定的值,而
eval(foo)
对该值调用eval。写入
eval(:foo)