目次
はじめに
この記事はCODE BASE OKINAWA Advent Calendar 2022 - Adventarの10日目のエントリーです。
今まで何気なく使っていた(&:method)
がどういう挙動をしているのか見ていきます。
↓こんなやつ
%w(urasoe naha ginowan).map(&:upcase) #=> ["URASOE", "NAHA", "GINOWAN"]
前知識
(&:)
を理解するために必要な知識をそれぞれ見ていきます。
Proc
Procとはブロックをオブジェクトにしたものです。
例えば↓のような使い方ができます。
square = Proc.new { |x| x ** 2 } square.call(3) #=> 9
&修飾
Procオブジェクトをブロックとして渡す場合には引数の前に&
が必要です。
square = Proc.new { |x| x ** 2 } [1, 2, 3, 4, 5].map(&square) # Procオブジェクトを渡しているので`:`はつかない #=> [1, 4, 9, 16, 25]
また、メソッドをブロックとして渡す場合は一度to_proc
でProcオブジェクトに変換する必要があります。
class Integer define_method :square do self ** 2 end end square = :square.to_proc # ① [1, 2, 3, 4, 5].map(&square) #=> [1, 4, 9, 16, 25]
(&:method)
を解読する
前知識を踏まえていよいよ(&:)
を解読してみます。
例のコードを読んでみる
例に挙げたコードをもう一度貼っておきます。
%w(urasoe naha ginowan).map(&:upcase) => ["URASOE", "NAHA", "GINOWAN"]
- &に
:upcase
が渡されます - &修飾に
:method
を渡すと①で見たProcオブジェクトへの変換が行われます。つまり、シンボルのメソッドに対しto_proc
が呼び出されます :upcase
が変換されたProcオブジェクトとなります- 3で変換されたProcオブジェクトがブロックとしてmapに渡されます
- その後Procの節で見たように、Procオブジェクトとなった
upcase
の.call()
引数に配列の各要素を受け取ります - mapメソッドはProcオブジェクトを実行した戻り値を新たな配列に追加します
上記のような流れを経て(&:method)
は動いているのですね。
まとめ
メタプログラミングRubyやチェリー本を読んで面白かったので自分なりに(&:method)
について整理してみました。
よきRubyライフを💎