LoginSignup
20
7

More than 3 years have passed since last update.

こんなメソッドまで?ブロックを受け取るRubyのメソッドたち

Posted at

動機

この記事はもともとLegalForceさんで行われたイベントのために調べ物をしていたのでそれを再利用したものです。
私はRubyの最大の強みの一つはブロックの表現力だと思うのですが、この記事ではそんなブロックを(実は)引数に受け取るメソッド群を紹介したいと思います。

本編

但し書き

今回はコアクラス(String, Array, Hash)のみに絞って紹介しています。
明らかにブロックを受け取ると思われるもの(例:each系のメソッド)などは除外されています。
その他、明らかに使い途がないと個人的に思われたものも除外しています。

String

String#gsub

個人的に意外だったものの筆頭は、gsubgsub!がブロックを受け取ることです。以下のように使います。

'hoge'.gsub(/[aiueo]/) {|match| match * 2 } # => hoogee

これはかなり便利そう。

String#match, Regexp#match

matchは正規表現に対して呼ぶのが王道な気はしますが、どちらもブロックを受けることができます。

str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
str.match(/^(.+) (.+)/) {|match| puts match[2] }
# "elit."が出力される

String#scan

存在自体を知らない人も多いであろうscanメソッド。matchの同じようなブロックの使い方ができます。

str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
str.scan(/\w+/) {|word| print "*#{word}*"}
# "*Lorem**ipsum**dolor**sit**amet**consectetur**adipiscing**elit*"が出力される。

Array

Array.new

今知ったのですが、Array.newはブロックを受けることができるようです。

Array.new(3) {|index| index ** 2} # => [0, 1, 4]

いつ使うんだろ…

Array#count

メジャーなメソッドであるcountも実はブロックを受け取ります。

ary = (0..10).to_a
ary.count {|e| e.even? } # => 6

これはとてもRuby的で綺麗だと思います。

Array#fetch

Hash#fetchと比べると使う機会は少ないですが、配列にもfetchメソッドがあります。

ary = (0..10).to_a
ary.fetch(100) {|i| puts "#{i} is out of range" }
# "100 is out of range"が出力される。

Array#index

ブロックがtrueを返す最初のインデックスを返します。こんなものあるんだ…

ary = (0..10).to_a
ary.index {|i| i.odd? } # => 1

Array#to_h

to_hってブロック受け取れるんだ…!

ary = (0..10).to_a
ary.to_h # => TypeError
ary.to_h {|e| [e.to_s, e ** e]} # => {"0"=>1, "1"=>1, "2"=>4, "3"=>27, "4"=>256, "5"=>3125, "6"=>46656, "7"=>823543, "8"=>16777216, "9"=>387420489, "10"=>10000000000}

何かに使えそう。

Hash

Hash#merge

これもすごく便利だと思ったやつで、ハッシュ同士を合体させるときにキーがコンフリクトしたものの処理をブロックで行うことができます。

h1 = {a: 1, b: 2}
h2 = {b: 3, c: 4}
h1.merge(h2) {|key, old, new| old + new} # => {:a=>1, :b=>5, :c=>4}

Hash#to_h

最初はよく意味がわからなかったのですが、Hash#to_hはブロックを受け取るとキーバリューペアをブロック引数として返り値の配列を新しいハッシュとすることができるようです。

{foo: 42}.to_h {|k, v| [k.upcase, v * 2]} # => {:FOO=>84}

これは実質mapしているということなのでしょうか…

まとめ

今回はコアクラスに絞ってブロックを受け取るメソッドを紹介しました。他にももちろんまだまだあるので、ぜひご自身で調べてみてください。

20
7
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
7