[解決済み] Juliaの「シンボル」とは何ですか?
質問
具体的には? JuliaのDataFramesパッケージ、特にreadtable()関数をnamesオプションで使おうとしていますが、これにはシンボルのベクトルが必要です。
- シンボルとは何ですか?
- なぜ、文字列のベクトルではなく、それを選ぶのか?
今のところ、Julia言語でsymbolという単語が使われているのは、ほんの一握りしか見つかっていません。シンボルは":var"で表現されるようですが、それが何であるかは私には到底理解できません。
余談ですが を実行することができます。
df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] )
箇条書きにした2つの質問はまだ有効です。
どのように解決するのですか?
JuliaのシンボルはLisp、Scheme、Rubyと同じです。ただし 答え これらの関連する質問に対して は本当に満足のいくものではありません 私見ですが。これらの回答を読むと、シンボルが文字列と異なる理由は、文字列が変更可能であるのに対してシンボルは不変であり、またシンボルは "interned" - それがどんな意味であれ - ということらしいです。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
シンボルオブジェクトは、コードを引用して得られる式オブジェクトの中にあります。
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のシンボルは、変数を表すために使われることはありません。
なぜDataFrameでは文字列ではなくシンボルが使われるかというと、DataFrameではユーザが用意した式の中でカラムの値を変数に束ねるのが一般的なパターンだからだそうです。つまり、変数をデータとして表現するために使うのがシンボルなのですから、カラム名がシンボルになるのは自然なことなのです。現状では
df[:foo]
にアクセスするために
foo
カラムとしてアクセスすることができますが、将来的には
df.foo
の代わりに それが可能になると、名前が有効な識別子であるカラムだけが、この便利な構文でアクセスできるようになります。
こちらもご覧ください。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン