search
LoginSignup
0
Help us understand the problem. What are the problem?

posted at

updated at

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

はじめに

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. ブロック引数が一つだけ

まとめ

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

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
What you can do with signing up
0
Help us understand the problem. What are the problem?