基本のデータ型(3)
ハッシュ
Rubyの中核となる最後のデータ構造が、.NET 1.0のHashtableに似たHash
です。ハッシュは連想配列で、添字(キー)に任意の種類の値を使うことができ、添字が参照するデータ(値)にも任意の種類のデータを使うことができます。実際には、ほとんどのハッシュでキーに記号が使われます(次のセクションを参照)。
ハッシュは{}
構文を使って宣言し、「キー => 値
」の形で初期値を宣言します。ハッシュで添字演算子を使って、値を取得および設定できます。
irb(main):050:0> h = {:foo=>'bar', :baz=>'biff'} => {:foo=>"bar", :baz=>"biff"} irb(main):051:0> h[:foo] => "bar" irb(main):052:0> h[:unknown] => nil irb(main):053:0> h[:baz] = "new" => "new" => {:foo=>"bar", :baz=>"new"} irb(main):054:0> h.entries => [[:foo, "bar"], [:baz, "new"]]
変数
Rubyの変数(およびメソッド)名は小文字で始まり、名前には英数字とアンダースコアを使うことができます。
ローカル変数には接頭辞は付きません。インスタンス変数には@
という接頭辞が付きます。グローバル変数には$
という接頭辞が付きます。変数を使う前に宣言する必要はありません。初期化していない変数には、値nil
が入ります。
次のように、定義済みの変数がいくつか用意されています。
nil
は、無を表すオブジェクトです(.NETのnull
に相当しますが、nil
はNilClass
クラスのインスタンスである点が異なります)。true
とfalse
は、TrueClassとFalseClassのインスタンスです。self
は、メソッドから使用されると、そのメソッドの呼び出し元のオブジェクトインスタンスへのポインタになります。クラス内で使用されると、クラスオブジェクト自体のインスタンスを表します。__FILE__
と__LINE__
は、現在実行中のファイルと、そのファイル内の行番号を返します。
シンボル
Rubyには、シンボルと呼ばれる特別な種類の文字列があります。Rubyでは文字列を変更できるため、文字列をハッシュキーとして使うと、よくても処理速度が遅く、悪くすると予測不可能になります。
シンボルの命名規則は変数と同じですが、シンボル名はコロン(:
)で始まる点が異なります。シンボルの値は変更できず、同じ名前の2つのシンボルは同じ識別情報を持ちます。このため、シンボルはハッシュキーとして使うのに適しています。可変長文字列の値を比較する代わりに、整数値と照合するだけで済むからです。
クラス
Rubyではあらゆるものがオブジェクトで、オブジェクトはすべてクラスのインスタンスです。あるオブジェクトのクラスを調べるには、そのオブジェクトのclass
メソッドを呼び出します。
5.class => Fixnum (2 ** 96).class => Bignum 7.5.class => Float (1..10).class => Range "foo".class => String /^foo[a-e]$/.class => Regexp :foo.class => Symbol [].class => Array {}.class => Hash
ブロックとクロージャ
.NET 1.xにはイベントハンドラのようなものがありましたが、イベントを処理したいときは、イベントにアタッチするすべてのメソッドを定義せざるを得ませんでした。このため、フレームワークで要求されているという理由だけで存在する多くのメソッドが作成されました。
.NET 2.0では、匿名デリゲートの概念が導入されました。匿名デリゲートは、Rubyのブロックとほぼ同じ働きをします。
irb(main):001:0> h = {:foo=>'bar', :hi=>'there'} => {:foo=>"bar", :hi=>"there"} irb(main):002:0> h.each_key {|k| puts k} foo hi => {:foo=>"bar", :hi=>"there"} irb(main):003:0> h.each {|k,v| puts "#{k}: #{v}"} foo: bar hi: there => {:foo=>"bar", :hi=>"there"}
このように、Rubyのブロックの構文はとても簡潔です。ブロックの開始と終了には中かっこを使い、|x,y|
構文でブロックに渡す変数を指定します。
.NET 2.0の匿名デリゲートと同様に、Rubyのブロックはクロージャのような働きもします。つまり、外側のスコープが終了した後でも、そのスコープにある値にアクセスできます。次に示すのは、複数の値を掛け合わせる簡単なクロージャです。
irb(main):004:0> n = [5, 6, 10] => [5, 6, 10] irb(main):005:0> t = 1 => 1 irb(main):006:0> n.each { |i| t *= i } => [5, 6, 10] irb(main):007:0> t => 300
ブロックへの参照を格納し、後から使うこともできます。
irb(main):008:0> t = 1 => 1 irb(main):009:0> f = lambda { |i| t *= i } => #<Proc:0x0818a7b0@(irb):9> irb(main):010:0> n.each &f => [5, 6, 10] irb(main):011:0> t => 300