読者です 読者をやめる 読者になる 読者になる

成らぬは人の為さぬなりけり

エンジニアライフをエンジョイする為のブログ

知らない内に活用してるメソッド to_proc

Ruby1.9を使用している人は知らないうちに(?)活用してると思いますが。
Ruby1.9から、Symbol#to_procを使用するのにライブラリは不要になりました。


初めて見た時は、なんじゃこりゃーー、と思ったけど、
意味が分かれば、どうってことは無い。
例えば、こんなコード

class Hoge
  attr_reader :name
  def initialize(name)
    @name = name
  end
end

p [Hoge.new("first"),Hoge.new("second"),Hoge.new("third")].map(&:name)
p [Hoge.new("first"),Hoge.new("second"),Hoge.new("third")].map{|hoge|hoge.name}

Scalaだとコンストラクタがもっと簡潔で良い感じに書けるんだけどなぁ。。。)
実行結果

["first", "second", "third"]
["first", "second", "third"]

簡単に説明すると、
今回のポイントはここ

map(&:name)

これは、

  • Symbol#to_proc
  • &がついた引数はto_procが呼び出される

という二点の複合技。
(本にもトリッキーと書いてあった気が、、、普通に使われてるけど)


要は、
「:name」のシンボルの「#to_proc」メソッドは
「引数に渡されたオブジェクトの#nameを呼び出す」というProcオブジェクトを返すわけです。
(↑の例の「{|hoge|hoge.name}」と同じ事ですよね)


やってみよう!

ruby-1.9.2-p290 :001 > class Hoge
ruby-1.9.2-p290 :002?>   def initialize(name)
ruby-1.9.2-p290 :003?>     @name = name
ruby-1.9.2-p290 :004?>     end
ruby-1.9.2-p290 :005?>   def name
ruby-1.9.2-p290 :006?>     p "-- Call My Name !!!!"
ruby-1.9.2-p290 :007?>     @name
ruby-1.9.2-p290 :008?>     end
ruby-1.9.2-p290 :009?>   end
 => nil 
ruby-1.9.2-p290 :010 > p = :name.to_proc
 => #<Proc:0x007fbf198a3060> 
ruby-1.9.2-p290 :011 > p.call(Hoge.new("Hoooooge!!"))
"-- Call My Name !!!!"
 => "Hoooooge!!" 
ruby-1.9.2-p290 :012 > 

うん、なるほど。


と、いうことは#to_procを定義すれば、なんかいろいろ出来そうだ。
ちょっとやってみよう。

class Amemiya
  def to_proc
    Proc.new { |o| "#{o}始めました"}
  end
end
p ["冷やし中華","塩ら〜めん","油そば"].map(&Amemiya.new)

実行結果

["冷やし中華始めました", "塩ら〜めん始めました", "油そば始めました"]

と、まぁ、実験としては、あまり役に立たない遊びをしてみるわけです。


深夜なので、お許しを。