Ruby力の基礎固めとして、ブロックについて学んだことをまとめます。
ブロックとは
メソッド呼び出しの際に引数と一緒に渡すことのできる処理のかたまり | たのしいRuby P199
ブロックつきメソッド呼び出しの例
[1, 2, 3, 4, 5].each do |i| # do ~ end は { ~ } でもOK
puts i ** 2
end
=> 1
4
9
16
25
ブロックの使い方
代表的な使い方が以下の3つです。
- 繰り返し
- 処理の隠蔽
- 処理の一部の差し替え
繰り返し
# 例)hash
sum = 0
outcome = {'join' => 1000, "shopping" => 1000, 'food' => 4000}
outcome.each do |item, price|
sum += price
end
puts sum
=> 6000
# 例)file読込
file = File.open('sample.txt')
file.each_line do |line|
print line
end
=> aaa
bbb
ccc
ddd
file.close
処理を隠す
# 例)自動的にファイルが閉じられる
file = File.open('sample.txt') do |file|
file.each_line do |line|
print line
end
end
=> aaa
bbb
ccc
ddd
計算の一部の差し替え
# Array#sortの場合
a = [3, 4, 5, 2, 6, 1, 7]
# ブロックなし
sorted = a.sort
=> [1, 2, 3, 4, 5, 6, 7]
# デフォルトの処理と同じ
sorted = a.sort do |a, b|
a <=> b
end
=> [1, 2, 3, 4, 5, 6, 7]
# リバース
sorted = a.sort do |a, b|
b <=> a
end
=> [7, 6, 5, 4, 3, 2, 1]
str_a = ["udon", "yakisoba", "somen", "ra---men"]
# 文字数順
sorted = str_a.sort do |a, b|
a.length <=> b.length
end
=> ["udon", "somen", "yakisoba", "ra---men"]
ブロックつきメソッドの作り方
ブロックの処理 → 合計値を算出するメソッドの例
def total(from, to)
result = 0
from.upto(to) do |num|
if block_given?
result += yield(num)
else
result += num
end
end
return result
end
p total(1, 10)
=> 55
p total(1, 10){|num| num ** 2}
=> 385
ブロック変数とyieldの引数の関係
ブロック変数とyieldの引数の数はあわなくてもエラーにはならない
# ブロック変数がyield引数より多い場合
def block_args
yield()
end
block_args do |a|
p [a]
end
=> nil
# ブロック変数がyield引数より少ない場合
def block_arg
yield(1,2,3)
end
block_arg do |a|
p a
end
=> 1
# ブロック変数を*aで受け取る場合
def block_arg
yield(1,2,3)
end
block_arg do | *a |
p a
end
=> [1, 2, 3]
ブロックのオブジェクト化
Procを使う。ブロックを別メソッドに引き渡すことが可能になる
# Proc変数を使用する例
def total2(from, to, &block) # &引数名にすると与えられたブロックはProcオブジェクト化される
result = 0
from.upto(to) do |num|
if block # 判定式も変更
result += block.call(num) # block.callで呼び出し
else
result += num
end
end
return result
end
ローカル変数とブロック変数
主な特徴は2つ
- ローカル変数はブロック内でも共有
- ブロック変数は外側とは切り離されている
参考
- たのしいRuby
- [Ruby] ブロックとProcをちゃんと理解する
- Rubyの動かないコード(初級編)ブロックとクロージャの性質