Juliaのシンボルは、Lisp、Scheme、Rubyと同じです。しかし、私の意見では、これらの関連する質問への回答は本当に満足できるものではありません。これらの回答を読んだ場合、記号が文字列と異なるのは、記号は不変であるのに文字列は変更可能であり、記号も「内部化」されているためです。RubyやLispでは文字列が変更可能ですが、Juliaでは変更できません。その違いは、実際には赤いニシンです。シンボルがインターンされる、つまり言語の実装によってハッシュされて等価比較が高速になるという事実も、実装の詳細とは無関係です。あなたはインターンシンボルを持たない実装を持つことができ、言語はまったく同じになるでしょう。
では、シンボルとは何でしょうか?答えは、JuliaとLispが共通に持っているもの、つまり言語のコードを言語自体のデータ構造として表現する能力にあります。これを「ホモニコ性」(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は同型ではないからです。Rubyはその式をRubyオブジェクトとして表現しません。したがって、Rubyのシンボルタイプは、痕跡器官の一種です。残りの改作であり、Lispから継承されますが、元の目的には使用されません。Rubyのシンボルは他の目的(メソッドをメソッドテーブルから取り出すためのハッシュキー)として採用されていますが、Rubyのシンボルは変数を表すために使用されていません。
文字列ではなくDataFramesでシンボルが使用される理由については、ユーザー提供の式の内部で変数に列の値をバインドするのがDataFramesの一般的なパターンであるためです。したがって、シンボルは変数をデータとして表すために使用するものとまったく同じであるため、列名がシンボルであることは自然です。現在、列df[:foo]
にアクセスするには書き込みが必要ですがfoo
、将来的にはdf.foo
代わりにアクセスできるようになる可能性があります。それが可能になると、この便利な構文を使用して、名前が有効な識別子である列にのみアクセスできます。
以下も参照してください。