Ruby on Rails 入門のための知識 1(シンボルとハッシュ)
Ruby on Railsの勉強に突入しました。
RoRはMVCモデルが分かってても実際の書かれているコードがいまいちよくわかんない状態になりがちです。特にハッシュとシンボルは理解していないとRoRのコードの意味が理解できないじゃないでしょうか。
ということでRoRを勉強するにあたって事前に知っておいた方がよい知識をまとめておきます。
今回は「シンボルとハッシュ」についてです。
Ruby初心者の愛読書「たのしいRuby 第3版」p41についてシンボルの説明があります。
シンボル(Symbol)というのは、文字列に似たオブジェクトで、Rubyがメソッドなどの名前の識別に使うラベルをオブジェクトにしたものです。
シンボルと同様のことはたいてい文字列でもできます。ハッシュのキーのように単純に「同じかどうか」を比較するような場合は、文字列よりも効率がよいことが多いので、シンボルもよく使われます。
たのしいRuby」全ページでシンボルの説明はこれだけです。
これだけでは初心者には全くわからないですね。でも大丈夫。私が代わりに調べました。
まずは文字列ハッシュからみてみましょう。
capital = {"france" => "Paris", "japan" => "Tokyo", "uk" => "London" }
次はシンボル
capital = {:france =>"Paris", :japan => "Tokyo", :uk => "London"}
シンボルで書いたほうがスッキリ。
ですが「文字列よりも効率がよい」の意味が解明されていないですね。
ここでなぜ「効率がよい」のかというとシンボルは参照型だからです。つまりオブジェクトが生成された後は常にそのアドレスを参照します。
ハッシュの値にシンボルを使うと、比較のために渡されたシンボルも同じアドレスを参照しているためstr文字列よりもRubyインタープリタの処理が断然速いわけです。
ゆえに、「たのしいRuby」が教えてくれたように、Hashキーのような文字列としてよりも、識別子としての文字列の場合はシンボルを使ったほうがいいということになりそうです。
(識別子というのは、例として、上記のハッシュで値は、Tokyoは絶対にTokyoじゃないと駄目ですね。TokやTokyでは駄目です。Tokyoは地名であって識別子ではないからです。ただしキーの場合はjapanでもいいしjpnでもいいしjpでもそれがプログラマに日本を意味しているのが識別できればいいわけです。)
今までの内容をRubyコードで検証してみましょう。
Rubyでオブジェクトの等値性を比べるときに便利なのが、euqal?とeql?メソッドです。
equal?はオブジェクトが同一オブジェクトを参照しているのか調べます。
eql?はobjectクラスではequal?と同義語として定義されていますが、再定義される場合は型が同じで値も等しいかを調べるように再定義される場合が多いです。
お持ちの方は、「たのしいRuby」 p68のコラムをご覧下さい。
「==」は比較する値同士のクラスが違っていても適当に変換して比較を行いますが、eql?メソッドは変換せずに比較を行っています。
ハッシュ内部のキーと与えられたキーとの比較など、多少厳密に比較を行う必要がある場合には、eql?メソッドが使われます。
コードを見てみましょう。
x ="paris" y ="paris" p x.equal?(y) # => false p x.eql?(y) # => true x =:paris y =:paris p x.equal?(y) # => true p x.eql?(y) # => true
eql?が共にtrueなので文字列でもシンボルでもハッシュのキーとしては妥当ですね。
ただ、同じシンボルならeql?とequal?での同一性が保障されるわけです。
※Numericをキーにする場合は1eql?(1.0)はfalseですので注意してください。
シンボルのほうが同一性あるし、スッキリしてて、実行も速い。
だったらハッシュにはシンボルでいいじゃんということです。
長い文章で疲れたと思います。が!
最後に大切なことをもう1つだけお教えします。
ハッシュリテラルについてです。
ハッシュの表記方法ですがRoRでよく使われるのは、
capital = { :france =>"Paris", :japan => "Tokyo", :uk => "London" }
ではなくて。下の書き方です。
capital = { france: "Paris", japan: "Tokyo" , uk: "London" }
キーにシンボルを使う場合はコロンをハッシュキーの最後につけると矢印を省略して書けますというRuby1.9の表記方法です。
この表記法には慣れておいたほうがよいです。
応用例を示してこの投稿は終わりにしたいと思います。
params = {} params[:user] ={ name: "Onsen Ruby", email: "onsenruby@onsen.com" } p params # => {:user=>{:name=>"Onsen Ruby", :email=>"onsenruby@onsen.com"}} p params[:user][:email] # => "onsenruby@onsen.com"