はじめに
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つの処理を行います。
- 配列の中身をひとつずつ繰り返す
- ブロックからの戻り値がtrueの場合にその要素を削除する
- oddメソッド は、奇数であればtrueを、そうでなければfalseを返す
挙動
下記を、配列aの要素の数だけ繰り返します。
- delete_ifメソッドにより、要素の値を取り出し、ブロックに処理が移る
- ブロックでは、|i|のブロック引数を介して、1.の値を受け取る
- 受け取った値を用いて、ブロック内のodd?メソッドが行われる
- oddメソッドがブロック内の最後の式になるため、その評価結果をdelete_ifメソッドに返す
- delete_ifメソッドは、ブロックから返された値を受け取り、その値がtrueであれば削除を行う
ブロックの持つ機能
上記のケースを踏まえ、ブロックには大きく二つの機能があることが分かります。
- 呼び出し元のメソッドから値を受け取り、
- ブロック内の最後の式の評価結果を、呼び出し元メソッドに返す
ブロックを使うメリット
今回のケースでは、
- delete_ifメソッドが持つ機能に対して
- odd?メソッドを呼び出した
わけですが、この2.部分は、ブロックの機能を使って、他の処理に書き換えてもいいわけです!
つまり、ブロックを用いれば、「共通処理」と「可変処理」を組み合わせた処理を記述することできるようになります!
ブロックを使うケース
ブロックとセットで使用する頻度の多いメソッドとして、下記3点が挙げられます。
- mapメソッド
- selectメソッド
- findメソッド
mapメソッド
mapメソッドとは、ブロックからの戻り値で、新しい配列を生成するメソッド
例えば下記のコードように、「配列の値を、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つの条件を満たす必要があります
- メソッドを一回呼び出す以外の式がない
- その式に引数がない
- ブロック引数が一つだけ
まとめ
なんとなく使ってたブロックでしたが、意外に奥が深かったです!
間違っている箇所やアドバイスがあれば、是非教えて頂きたいです!