Ruby1.9のlambdaをアロー演算子に。Hash#perlish!

Ruby1.9ではlambdaを->で書けるようになりました。

lambda { |x| x+1 }  # これと
-> x { x+1 }        # これは等価

lambdaと->は文法上の扱いが異なります。

p(lambda{})   # => <Proc:0x9696dc@(irb):1 (lambda)>
plambda{}     # NoMethodError
p(->{})       # => <Proc:0x95e29c@(irb):2 (lambda)>
p->{}         # => <Proc:0x95bea0@(irb):3 (lambda)>

要するに->{}はデリミタ不要ということです。楽しいですね。
ところで、p->{}なんて形はPerlのリファレンスにしか見えません。なのでPerl風のアクセスができるようにしてみましょう。

$binding = binding

class Hash
  def perlish!(bind = $binding)
    id = self.object_id
    that = self
    bind.eval("local_variables").each{|sym|
      if id == bind.eval("#{sym.to_s}.object_id")
        Object.__send__(:define_method, sym, -> x { that[x.call] })
        break;
      end
    }
  end
end

こんなスクリプトを実行すると、

h = {"key" => :value}
h["key"]     # => :value

h.perlish!

p h->{"key"} # => :value
p h.class    # => Hash

Perlのリファレンスみたいな感じでHashにアクセスできるようになります{"def"}みたいなことはできない。">*1。楽しいですね。

*1:文法の制約からリファレンスを引けるのは一段まで。h->{"abc"}->{"def"}みたいなことはできない。