0
1

More than 1 year has passed since last update.

【Ruby】ブロックについてまとめてみた!

Last updated at Posted at 2022-06-20

はじめに

Rubyのブロックについて、勉強したことをまとめました!

ブロックとは

メソッドに渡せる処理のかたまりのこと

ブロックと引数の違い

どちらもメソッドに渡すものというのは共通していますが、

  • 引数は「オブジェクト」を渡すもの
  • ブロックは「処理」を渡すもの
    になります。

ブロックの記述方法

下記のように2通りの書き方があります!

a = [1,2,3]
# ① doからendまでがブロック
a.each do |n| #|n|は「ブロックパラメータ」と呼ぶ
    #処理内容をここに書く    
end

# ② {}内がブロック
a.each { |n| #処理内容をここに書く }

ブロックの機能・挙動・メリットについて

下記の「配列内にある奇数を削除する」コードを用いて説明します!

配列内にある奇数を削除する
a = [1,2,3,4,5]
a.delete_if do |i|
    i.odd?
end
puts a #=> 2,4

前提

上記コードを読む上での前提になります!

  • delete_ifメソッドは、下記の2つの処理を行います。
    1. 配列の中身をひとつずつ繰り返す
    2. ブロックからの戻り値がtrueの場合にその要素を削除する
  • oddメソッド は、奇数であればtrueを、そうでなければfalseを返す

挙動

下記を、配列aの要素の数だけ繰り返します。

  1. delete_ifメソッドにより、要素の値を取り出し、ブロックに処理が移る
  2. ブロックでは、|i|のブロック引数を介して、1.の値を受け取る
  3. 受け取った値を用いて、ブロック内のodd?メソッドが行われる
  4. oddメソッドがブロック内の最後の式になるため、その評価結果をdelete_ifメソッドに返す
  5. delete_ifメソッドは、ブロックから返された値を受け取り、その値がtrueであれば削除を行う

ブロックの持つ機能

上記のケースを踏まえ、ブロックには大きく二つの機能があることが分かります。

  1. 呼び出し元のメソッドから値を受け取り、
  2. ブロック内の最後の式の評価結果を、呼び出し元メソッドに返す

ブロックを使うメリット

今回のケースでは、

  1. delete_ifメソッドが持つ機能に対して
  2. odd?メソッドを呼び出した
    わけですが、この2.部分は、ブロックの機能を使って、他の処理に書き換えてもいいわけです!
    つまり、ブロックを用いれば、「共通処理」と「可変処理」を組み合わせた処理を記述することできるようになります!

ブロックを使うケース

ブロックとセットで使用する頻度の多いメソッドとして、下記3点が挙げられます。

  1. mapメソッド
  2. selectメソッド
  3. findメソッド

mapメソッド

mapメソッドとは、ブロックからの戻り値で、新しい配列を生成するメソッド
例えば下記のコードように、「配列の値を、10倍にして返す処理」を行う場合に使用します。

配列の値を、10倍にして返す例
a = [1,2,3,4,5]
b = a.map {|i| i * 10}

p b #=>[10, 20, 30, 40, 50]

selectメソッド

selectメソッドは、ブロックからの戻り値が真の場合のみ、その要素を配列に格納するメソッド
例えば下記のコードのように、「配列から偶数のみ抽出し、新しい配列をつくる」場合などに使用します。

配列から偶数のみ抽出し、新しい配列をつくる例
a = [1,2,3,4,5]
b = a.select {|i| i.even? }
p b #=>[2,4]

findメソッド

findメソッドは、ブロックの戻り値が真になった最初の要素を返します。
例えば下記のコードのように、「配列の一番最初の偶数を探す」場合などに使用します。

配列の一番最初の偶数を探す
a = [1,2,3,4,5]
b = a.find {|i| i.even? }
p b #=>2

ブロックに渡す配列を簡潔に書く方法

下記のように、ブロックに配列を渡すときは、より簡潔に書くことができます!

ブロックに渡す配列を簡潔に書く例
a = [
    [10,20],
    [5,10],
    [10,10],
] 
result = []

#ブロック引数が1つの場合
a.map do |i|
    left = i[0]
    right = i[1]
    result << left * right
end
p result #=> [200,50,100]

#ブロック引数が2つの場合(上記より簡潔になる)
result = []
a.map do |left,right|
    result << left * right
end
p result #=> [200,50,100]

&とシンボルを使って簡潔に書く

下記のコードは、&:メソッド名の書き方をすると、より簡潔に書けるようになる

&:メソッド名で書いた例
a = [1,2,3]

a.select{|n| n.odd?}

#上記を「$:メソッド名」で書いた場合
a.select(&:odd?)

&:メソッド名で書くための条件

下記3つの条件を満たす必要があります

  1. メソッドを一回呼び出す以外の式がない
  2. その式に引数がない
  3. ブロック引数が一つだけ

まとめ

なんとなく使ってたブロックでしたが、意外に奥が深かったです!
間違っている箇所やアドバイスがあれば、是非教えて頂きたいです!

0
1
2

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
0
1