朱莉娅的"象征"是什么?

Mag*_*eek 114 julia

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

  • 什么是象征?
  • 为什么他们会选择一个字符串向量?

到目前为止,我发现只有少数几个对朱莉娅语中的单词符号的引用.看起来符号用":var"表示,但我不清楚它们是什么.

旁白:我可以跑

df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] )
Run Code Online (Sandbox Code Playgroud)

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

Ste*_*ski 201

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

那么什么是象征,真的吗?答案在于Julia和Lisp的共同点 - 能够将语言代码表示为语言本身的数据结构.有些人称之为"同性恋"(维基百科),但其他人似乎并不认为单独就足以让语言成为同性恋.但术语并不重要.关键是,当一种语言可以代表自己的代码时,它需要一种方式来表示诸如赋值,函数调用,可以写成文字值的东西等等.它还需要一种方法来表示自己的变量.即,你需要一种方法来表示 - 作为数据 - foo在左侧:

foo == "foo"
Run Code Online (Sandbox Code Playgroud)

现在我们谈到问题的核心:符号和字符串之间的差异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"
Run Code Online (Sandbox Code Playgroud)

符号的: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
Run Code Online (Sandbox Code Playgroud)

除了其他事项之外,抛出的东西显示的是,: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"
Run Code Online (Sandbox Code Playgroud)

如果在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""
Run Code Online (Sandbox Code Playgroud)

很明显,为什么这不起作用 - 如果你试图"foo" = "bar"手动分配,它也将无法工作.

这是符号的本质:符号用于表示元编程中的变量.当你将符号作为数据类型时,将它们用于其他事物(例如哈希键)变得很诱人.但这是一种偶然的,机会主义的数据类型用法,它具有另一个主要目的.

请注意,我暂时不再谈论Ruby了.那是因为Ruby不是homoiconic:Ruby并没有将其表达式表示为Ruby对象.所以Ruby的符号类型是一种退化器官 - 一种遗留的改编,继承自Lisp,但不再用于其原始目的.Ruby符号已被用于其他目的 - 作为哈希键,用于从方法表中提取方法 - 但Ruby中的符号不​​用于表示变量.

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

也可以看看:

  • 实习:在计算机科学中,字符串实习是一种仅存储每个不同字符串值的一个副本的方法,该副本必须是不可变的。驻留字符串使一些字符串处理任务在时间或空间上更加高效,代价是在创建或驻留字符串时需要更多时间。https://en.wikipedia.org/wiki/String_interning (8认同)
  • 非常如此:“eval(:foo)”给出变量“foo”绑定的值,而“eval(foo)”对该值调用 eval。编写“eval(:foo)”相当于“foo”(在全局范围内),因此“eval(foo)”类似于“eval(eval(:foo))”。 (4认同)
  • > 但将来,您也许可以以 df.foo 的形式访问它。现在是可能的 (3认同)
  • @niutech ...很难顶! (2认同)
  • 在某一时刻你写了“eval(:foo)”,在另一个时刻写了“eval(sym)”。`eval(:foo)` 和 `eval(foo)` 之间有有意义的区别吗? (2认同)
  • 未来是现在_。 (2认同)

Bog*_*ski 6

参考截至目前的原始问题,即 0.21 版本(以及未来)DataFrames.jl 允许将Symbols 和字符串用作列名,因为在不同情况下支持两者都不是问题,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
Run Code Online (Sandbox Code Playgroud)