Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【Ruby】array.map(&:method)を理解する

概要

Rubyで書かれたコードを見ていると度々array.map(&:メソッド名)の形式のイディオムを見かけると思います。そこで、array.map(&:メソッド名)がどのような動きをし、またなぜそのような動きをするのかまとめました。

何をする?

簡単にいうと以下のように配列の要素1つ1つに(&:メソッド名) で与えられたメソッドを呼んでいます。
(以下の例では文字列のabに対してString#upcaseメソッドを呼んでいます。

['a' ,'b'].map(&:upcase) #=> ["A", "B"]

なぜこのような結果になる?

引数にある&

まず、Rubyが引数内で&を見つけるとその値をプロック(proc)として扱おうとし、その値(この場合:upcase)に対してto_procメソッドを呼びます。

class Symbol
  def to_proc
    puts "to_procが呼ばれました!"
  end
end

p [].map(&:upcase) #=> to_procが呼ばれました!
## その後TypeErrorが発生。

Symbol#to_procメソッドとは?

to_procメソッドはその名の通り、渡されたシンボルを手続きオブジェクトのprocとして返すものです。

prc = :upcase.to_proc 
p prc #=> #<Proc:0x00007f99d303e458(&:upcase)>

作成したprcを文字列に呼んでみます。

p prc.call("string") #=> STRING

まとめると以下の事を行なっています。

:upcase.to_proc.call("string")#=> STRING

結論

つまり、array.map(&:メソッド名)(&:メソッド名)部分は:メソッド名.to_proc.callを省略した形という事になります。
以下の例で実際に両者の比較をみてみます。

# array.map(&:メソッド名)の記法
['a','b'].map(&:upcase) #=> ["A", "B"]

# 省略しない記法
['a','b'].map do |string|
  :upcase.to_proc.call(string)
end
#=> ["A", "B"]

参考

Understanding Ruby's idiom: array.map(&:method)
https://therealadam.com/2008/05/01/beautiful-multi-line-blocks-in-ruby/

k-penguin-sato
最近はGoとTypeScriptを頑張ってます。 https://dev.to/ksato1995
updata
不動産DXを推進しています。 主なプロダクト Syncaデータコンバーター Syncaワークフロー Syncaウェブサイト
https://updata.tech
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away