人気ブログランキング | 話題のタグを見る

RoR と send

config/boot.rb の記述の中にシンボルを引数として与えているものがある。

Rails::Initializer.run(:install_gem_spec_stubs)

がそれだ。

この、:install_gem_spec_stubs というシンボルは、boot.rb のなかで定義されているものではない。一体どこから来たのだろうか。じつは、これは、Rails::Initializer.run メソッドに渡された、Rails::Initializer クラスのインスタンスメソッドを表すシンボルなのだ。抽象的に言っても何のことか分からないので例を上げてみる。まずクラス A を作りそれに hello と bye というインスタンスメソッドを作る。

class A
  def hello
    puts 'hello'
  end

  def bye
    puts 'good-bye'
  end
end

そうすると、a = A.new で A のインスタンスを作り、a.hello で hello を、a.bye で good-bye を表示させることができる。

ところが send というメソッドを使うと、send の引数に、:hello つまり hello メソッドのシンボルを与えると、a.send(:hello) で a.hello と同じ動作をさせることができるのだ。

同じことをことさら面倒にしなくても良いようだが、次のような場合、シンボルの配列からイテレータで次々に a の振る舞いをコントロールできるので便利なのだ。

irb(main):011:0> [:hello, :bye].each{|m| a.send(m)}
hello
good-bye

これは言い換えると関数を引数にしてブロックに渡している。つまり高階関数を実現していることになる。関数を引数にすることができると色々と便利だ。たとえば次のプログラムは、hello を2回、good-bye を5回表示することができる。

irb(main):012:0> [[:hello, 2],[:bye, 5]].each{|m,n| n.times{ a.send(m) }}
hello
hello
good-bye
good-bye
good-bye
good-bye
good-bye

これを高階関数を使わずにプログラムしようとしたらとても上のようにコンパクトにはいかないだろう。

こういうわけで冒頭のコードは高階関数に関数を引数として渡していたのだ。
by tnomura9 | 2008-10-21 23:21 | Ruby | Comments(0)
<< RoR config/boot... RoR Rails モジュールの調査 >>