Rubyのシンボルを丁寧に理解する
Rubyのシンボルについてふわっと理解している状態だったので、きちんと説明できるくらいに理解しようとRubyのドキュメントを読み直しました。
シンボルとは?
Rubyのシンボルってどういうものかというと、以下のコードの「:fuga」のことです。ハッシュのデータを扱う時に見かけることが多いです。
hoge[:fuga] = 1
そしてシンボルの実態は何なのかというと、シンボルというオブジェクトです。公式ドキュメントではシンボルについて以下の説明がされています。
Rubyの内部実装では、メソッド名や変数名、定数名、クラス名などの`名前'を整数で管理しています。これは名前を直接文字列として処理するよりも速度面で有利だからです。そしてその整数をRubyのコード上で表現したものがシンボルです。
つまりシンボルとは見た目は文字列のように見えますが、内部では整数で扱われているシンボルというオブジェクトになります。
p :book.class #=> Symbol
p 'book'.class #=> String
シンボルと文字列の違いは?
そもそもオブジェクトが異なるということがわかりましたが、もう少し詳しく違いを見ていきます。
シンボルは書き換えられない
文字列はmutableで変更可能なオブジェクトですが、シンボルはImmutableなので変更することができません。
'book'.upcase! #=> "BOOK"
:book.upcase! #=> NoMethodErrorが発生します
シンボルは同値ならば必ず同一
シンボルはImmutableなので同値の場合は同じobject_idが割り当てられ、同じオブジェクトを指すことになります。
'book' == 'book' #=> true
'book'.equal?('book') #=> false
:book == :book #=> true
:book.equal?(:book) #=> true
比較の処理はシンボルの方が高速
値の比較を行う時、文字列を使う場合はその度に新しく文字列を生成する必要がありますが、シンボルはその必要がないためメモリの効率がよく、また高速に比較することができます。
シンボルと文字列の使い分けは?
- シンボルは書き換えられない
- シンボルは同値ならば必ず同一
- 比較の処理はシンボルの方が高速
以上のシンボルの特徴から、区別しなくても良いデータであればシンボルに置き換えた方がメリットは多そうです。
例えば最初のコードの例で出したハッシュの場合。
hoge[:fuga] = 1
ハッシュのキーとして使う値は文字列である必要はありません。整数でもいいのです。であれば、見た目からもデータの意図が分かりやすいシンボルを使う方が適切なのでしょう。
まとめ
ちゃんと誰かに説明できるくらいにシンボルについて理解ができたと思います。ちなみにJavaScriptにもSymbolというデータ型が存在しますが、全くの別物です。
Discussion