暗黙の Proc化(Ruby)

[1] pry(main)> (1..4).map {|i| i + 3}
=> [4, 5, 6, 7]

これと

[2] pry(main)> (1..4).map(&->(i) {i + 3})
=> [4, 5, 6, 7]

は同じ。引数での & は Proc をブロックに変換するから。(正確にはさらにそれを暗黙に .call() している。)


では、

[3] pry(main)> (1..4).map(&3)
TypeError: wrong argument type Integer (expected Proc)

はもちろんエラーになるよね。でも、この &3 のとき、3 は Proc でないので、暗黙に 3 を to_proc しようとしている。それを示してみよう。

Integer クラスにこうモンキーパッチしてみる。

[4] pry(main)> class Integer
[4] pry(main)*   def to_proc  
[4] pry(main)*     ->(i){i + self}    
[4] pry(main)*   end    
[4] pry(main)* end  
=> :to_proc

Integer を Proc化するのである。すると、

[5] pry(main)> (1..4).map(&3)
=> [4, 5, 6, 7]

おお、先ほどと同じだ。つまり、ここでは暗黙に 3 を to_proc しているのである。うーん、すごいですなあ。

つまり、オブジェクトに to_proc を定義しておくと、このような遊び(?)ができるわけです。可読性がなにですが。