A Day in the Life

RubyのSymbol

Rubyを最初学んだとき、SymbolとStringの違いが解って無くて、なら全部StringでいいやとSymbolを全く使わなかった時期がありました。今は意図的に使い分けるようにしています。Lost-Season: Rubyのシンボル で疑問点が上がっていたので、初心者向けにSymbolについて説明してみます。

まず使い道ですが、文字の定義を明確にしたいときに使うことが多いです。たとえばhashのkeyだったり、アクセサの引数で渡すインスタンス変数名だったり、alias_methodの引数で渡すメソッド名だったりと、文字に意味づけしたい時に使えます。このようなときにSymbolを使うことによって、ソースがすっきりして可視性が上がります。

また、symbolを使うと速度が向上します。これは、'a' と書くと毎回Stringの'a'を生成しコストが発生しますが、:aと書くと初回にしかコストが発生しません*1。比較も高速に行えます。

ただ、Hashのkeyとして使うとき、人によっては

hash = {:a => 'foo', :b => 'bar'}

と書いたり、

hash = {'a' => 'foo', 'b' => 'bar'}

と書いたりし、keyがsymbolかstringか解らなくて結局の所ソースを実際に確かめるケースが発生します。Railsではそれを取り除くために、active_supportで定義されているHashWithIndifferentAccessクラスを使い回避しています。これはHashのkeyがsymbolだった場合はstringにキャストされ、symbolでもstringでもvalueにアクセスできるようになっています。これで

url_for :controller => 'foo', :action => 'bar'
 url_for 'controller' => 'foo', 'action' => 'bar'

とHashのkeyがstring, symbolどちらでも利用することができます。しかしsymbolからstringへのキャストを毎回するため、速度的には遅くなってしまいます*2が、使いやすさ優先の考え方なのでしょう。

*1: 'a'.equal? 'a' はfalseだが:a.equal? :aはtrue

*2:ベンチマークを取ってみたところ、2倍強差(でも10万回ループで0.275367秒 => 0.664770秒 だけど)

記事の一覧 >