Ruby のシンボル(続き)
昨日の記事の続き。
あれからいろいろ探し回ってみたらこんな記事が。
『Lost-Season - Rubyのシンボル』のコメント欄より。
RailsではHashを拡張してkeyにstringとsymbolどちらを指定しても同じvalueが返されるようなクラスなども存在します。
なるほど。やはり Rails がうまくやってくれてたのか。
で、もう少しシンボルについて調べていたら、シンボルを使うことの意味について解説された記事を発見。
『川o・-・)<2nd life - RubyのSymbol』
まず使い道ですが、文字の定義を明確にしたいときに使うことが多いです。たとえばhashのkeyだったり、アクセサの引数で渡すインスタンス変数名だったり、alias_methodの引数で渡すメソッド名だったりと、文字に意味づけしたい時に使えます。このようなときにSymbolを使うことによって、ソースがすっきりして可視性が上がります。
また、symbolを使うと速度が向上します。これは、'a' と書くと毎回Stringの'a'を生成しコストが発生しますが、:aと書くと初回にしかコストが発生しません*1。比較も高速に行えます。
だそうです。なるほど。
で、同じ記事の後半には以下のように書いてある。
keyがsymbolかstringか解らなくて結局の所ソースを実際に確かめるケースが発生します。Railsではそれを取り除くために、active_supportで定義されているHashWithIndifferentAccessクラスを使い回避しています。
Rails でシンボルと String の変換をやってくれているのは ActiveSupport の HashWithIndifferentAccess というクラスとのこと。
さっそく調べてみるとindifferent_access.rb 内に conver_key というメソッドがあり
def convert_key(key) key.kind_of?(Symbol) ? key.to_s : key end
として、シンボルなら文字列に変換、String ならそのままでキーの検索をしていた。なるほど。
というわけで昨日からの疑問が解決。うーん、奥が深い・・・