概要
Rubyを初めて触ったときに、(当時の自分が触っていた)C#とJAVAではコロンが使われておらず、 これはどのような意味なのかがよく話からたかったので、まとめてみました。
:symbol "symbol"
こちらの違いについてまとめます。
Rubyにおけるコロンの意味とは?
Rubyにおけるコロンは、シンボルといいます。
:symbol
一見文字列と同種に見えるが、内部的には数値として扱われます。
そのため、比較や検索などの速度面が文字列と比べると高速になります。
- ハッシュのキー
- メソッドの引数として渡すクラス名、メソッド名、変数名、定数名
などについては、はシンボルを使用したほうが良いでしょう。
リファレンスでは
リファレンスを引用します。
Rubyの内部実装では、メソッド名や変数名、定数名、クラス名など の'名前'を整数で管理しています。これは名前を直接文字列として処理するよりも 速度面で有利だからです。そしてその整数をRubyのコード上で表現したものがシンボルです。 シンボルは、ソース上では文字列のように見え、内部では整数として扱われる、両者を仲立ちするような存在です。 名前を管理するという役割上、シンボルと文字列は一対一に対応します。 また、文字列と違い、immutable (変更不可)であり、同値ならば必ず同一です。
文字列と見せかけて、内部の実装では整数として扱っている。といったところでしょうか。
検証してみた
> Rubyの内部実装では、メソッド名や変数名、定数名、クラス名など の'名前'を整数で管理しています。
つまり、メソッド名や変数名、定数名、クラス名を定義した瞬間にシンボルができるという意味です。 実際にやってみましょう。
class SymbolTest end symbol_var = 0 SYMLBOL_CONSTANT = 0 def symbol_method end p Symbol.all_symbols.include?(:SymbolTest) => true p Symbol.all_symbols.include?(:symbol_method) => true p Symbol.all_symbols.include?(:symbol_var) => true p Symbol.all_symbols.include?(:SYMLBOL_CONSTANT) => true
見事に全てtrueを返しましたね。
> これは名前を直接文字列として処理するよりも 速度面で有利だからです。
文字列と数値なので、そりゃ高速になるだろうと反射的に思いましたが、こちらも検証してみます。
benchmark
というモジュールを使用して計測してみます。
実際のやり方はこちらを参考にしました。
Ruby でベンチマークを取る方法 - Qiita
require 'benchmark' Benchmark.bm 10 do |r| str = "0123456789" str_hash = { "0123456789" => 1 } r.report "String" do 9999999.times { str_hash[str] } end sym = :"0123456789" sym_hash = { "0123456789" => 1 } r.report "Symbol" do 9999999.times { sym_hash[sym] } end end user system total real String 1.190000 0.000000 1.190000 ( 1.190577) Symbol 0.810000 0.000000 0.810000 ( 0.815450)
文字列に比べて、シンボルは30%前後早くなっていますね。 すごいぞシンボル。
> 名前を管理するという役割上、シンボルと文字列は一対一に対応します。 また、文字列と違い、immutable (変更不可)であり、同値ならば必ず同一です。
同じ名前のシンボルであれば、いくつ生成してもオブジェクトIDが1つという意味ですかね。
hoge1 = "hoge" hoge2 = "hoge" puts hoge1.equal?(hoge2) => false puts hoge1.object_id => 70281989413340 puts hoge2.object_id => 70281989361520 sym1 = :hoge sym2 = :hoge puts sym1.equal?(sym2) => true puts sym1.object_id => 539048 puts sym2.object_id => 539048
こちらもリファレンス通りですね。
まとめ
冒頭でも書きましたが、Rubyにおけるコロンは、"シンボル"と呼びます。 一見文字列と同じように見えますが、内部的には整数と同様に扱われます。 そのため
- 文字列と比較すると処理が高速
- 同じ値であれば、生成されるオブジェクトは1つ。
また、クラス、メソッド、変数、定数を定義すると、その名前のシンボルも生成されます。
文字列とシンボルの使い分けとしては、
- ハッシュのキー
- メソッドの引数として渡すクラス名、メソッド名、変数名、定数名
などは、文字列ではなく、シンボルを使用したほうが良いでしょう。
こちらの本はRubyについて、今でもリファレンス的に使用している本なので、オススメします。
※今回のシンボルについては、ここまで詳細には書かれていませんが、全範囲を網羅的に書かれています。