概要
array.map { |a| a.method }
を array.map(&:method)
と略記できるやつの仕組みを何度調べても忘れるのでメモ。
これに関する記事は他にも多くありますが、自分の中で咀嚼したつもりのものを書き残します。
本文
前提
to_proc
を持つオブジェクトの頭に &
をつけてメソッドの引数として渡すと、 to_proc
が実行されProcオブジェクトとなり、メソッドにブロックとして渡される。
また、Symbolクラスのインスタンスメソッド to_proc
は、シンボルと同名のメソッドを呼び出し、第1引数をそのメソッドのレシーバとする。
つまり
# これの &:upcase 部分は
['hoge', 'fuga'].map(&:upcase)
# to_proc してメソッドに渡されるのでこれと同じ
proc = :upcase.to_proc
['hoge', 'fuga'].map(&proc)
# Symbol#to_proc は Proc.new したこれに置き換えられる
# (厳密にはlambdaらしいがわかりやすさのためにこれで)
proc = Proc.new { |a| a.upcase }
['hoge', 'fuga'].map(&proc)
# そしてそれはもはや直接ブロックを渡すこれと同じ
['hoge', 'fuga'].map { |a| a.upcase }