こんにちは。Tomoyuki(@tomoyuki65)です。
Rubyではブロックが使えますよね。
基本的にはRuby標準のメソッドでブロックを使いますが、自分で作成したメソッドでもブロックが使えるんです。
この記事では、Rubyのブロックについて解説します。
目次
ブロックとは?
ブロックとは、メソッドの引数として渡すことができる処理のかたまりです。
例えば、以下のようなプログラムのdo〜endを指します。
num = [10, 20, 30] sum = 0 num.each do |n| sum += n end
尚、do〜endは { } で置き換えることもできます。
num = [10, 20, 30] sum = 0 num.each { |n| sum += n }
メソッドでブロックを使う方法
自分で作成したメソッドでもブロックを使うことができます。
例えば、メソッドからブロックの処理を呼び出す場合は、以下のように「yield」を使います。
def test_block
puts "Start"
yield
puts "End"
end
test_block do
puts "ブロックを渡す"
end
ブロックを渡す
End
実行結果の通り、メソッドの「yield」にブロックが渡され、ブロックの処理が行われます。
メソッドからブロックに引数を渡す
メソッドからブロックに引数を渡すこともできます。
例えばブロックに引数を渡したい場合は、以下のように書きます。
def test_block
puts "Start"
yield "メソッドから引数を渡す"
puts "End"
end
test_block do |text|
puts text
end
メソッドから引数を渡す
End
ブロックがメソッドに渡されたかを確認
ブロックがメソッドに渡されたかを確認することもできます。
その場合は「block_given?」メソッドを使用します。
def test_block
puts "Start"
# ブロックが渡された場合のみ実行する
if block_given?
yield
end
puts "End"
end
# ブロックなしで実行
test_block
# ブロックありで実行
test_block do
puts "ブロックを渡す"
end
end
Start
ブロックを渡す
End
ブロックを引数として明示的に受け取る
ブロックをメソッドの引数として明示的に受け取ることもできます。
ブロックを引数として受け取る場合は、引数名の前に「&」を付け、ブロックを実行する場合はcallメソッドを使います。
def test_block(&block)
puts "Start"
# callメソッドでブロックを実行
block.call
puts "End"
end
test_block do
puts "ブロックを渡す"
end
ブロックを渡す
End
このように、Ruby標準のメソッドだけでなく、自分で作ったメソッドにもブロックを使うことができます。
Procクラスによるブロックのオブジェクト
Procクラスを使用すると、ブロックをオブジェクト化することができます。
Procオブジェクトを実行する場合は、callメソッドを使います。
例として、以下のプログラムを実行してみて下さい。
block_proc = Proc.new do
puts "Procオブジェクト"
end
block_proc.call
また、実行時に引数を利用することもできます。
block_proc = Proc.new do |text|
puts "Procオブジェクト + #{text}"
end
block_proc.call('引数を利用')
Procオブジェクトをメソッドの引数に渡す
Procオブジェクトは、メソッドの引数として渡すことができます。
先ほどの「ブロックを引数として明示的に受け取る」で確認したプログラムのブロックを、Procオブジェクトに変更しても渡すことができます。
def test_block(&block)
puts "Start"
# callメソッドでブロックを実行
block.call
puts "End"
end
block_proc = Proc.new { puts "ブロックを渡す" }
test_block(&block_proc)
ブロックを渡す
End
また、Procオブジェクトは、普通の引数としても渡すことができます。
普通の引数として渡す場合は、「&」を付けないことに注意して下さい。
def test_block(block)
puts "Start"
# callメソッドでブロックを実行
block.call
puts "End"
end
block_proc = Proc.new { puts "ブロックを渡す" }
test_block(block_proc)
ブロックを渡す
End
ブロックとして渡す場合と普通の引数として渡す場合の違いとして、メソッドが受け取れるブロックの数は1つですが、普通の引数であれば制限はありません。
Procオブジェクトを作るもう一つの方法
Procオブジェクトは、「->」(ラムダリテラル)または「lambda」メソッドを使っても作ることができます。
def test_block(block)
puts "Start"
# callメソッドでブロックを実行
block.call
puts "End"
end
block_proc = -> { puts "ブロックを渡す" }
test_block(block_proc)
ブロックを渡す
End
Procとラムダの違い
Procとラムダはほぼ同じものですが、以下のような違いがあります。
- ラムダは引数のチェックが厳密
- returnとbreakを使った場合の挙動が異なる
ラムダは引数のチェックが厳密
ブロックに引数を渡す場合、ラムダは引数に過不足があるとエラーになります。
# Procの場合
block_proc = Proc.new { |text| puts text }
block_proc.call("a","b")
# ラムダの場合はエラー
block_rambda = ->(text) { puts text }
block_rambda.call("a", "b")
from Main.rb:14:in `’
returnとbreakを使った場合の挙動が異なる
Procやラムダの内部でreturnやbreakを使った場合に挙動が異なります。
returnの場合、Procではメソッドを抜けますがラムダはメソッドを抜けません。
# Procの場合
def proc
puts "proc_start"
block_proc = Proc.new { |text| return puts text }
block_proc.call([1, 2, 3])
puts "proc_end"
end
# ラムダの場合
def rambda
puts "rambda_start"
block_rambda = ->(text) { return puts text }
block_rambda.call([1, 2, 3])
puts "rambda_end"
end
# procメソッドを実行
proc
# rambdaメソッドを実行
rambda
1
2
3
rambda_start
1
2
3
rambda_end
またbreakの場合は、Procではエラーになりますがラムダはエラーになりません。
# Procの場合
def proc
puts "proc_start"
block_proc = Proc.new { |text| break puts text }
block_proc.call([1, 2, 3])
puts "proc_end"
end
# ラムダの場合
def rambda
puts "rambda_start"
block_rambda = ->(text) { break puts text }
block_rambda.call([1, 2, 3])
puts "rambda_end"
end
# procメソッドを実行(エラーとなる)
proc
# rambdaメソッドを実行
rambda
from Main.rb:5:in `proc’
from Main.rb:19:in `’
このように、メソッドでブロックを使う場合は色々な書き方があるため、それぞれの仕様を理解した上で使いわけれると良さそうです。
まとめ
- ブロックはメソッドの引数として渡すことができる処理のかたまり
- メソッドからブロックの処理を呼び出す場合は「yield」を使う
- 「yield」の後に引数を書くと、ブロックに引数を渡すことができる
- ブロックがメソッドに渡されたかを確認するには「block_given?」メソッドを使う
- ブロックを引数として受け取る場合、引数名の前に「&」を付け、ブロックを実行する場合はcallメソッドを使う
- Procクラスを使用すると、ブロックをオブジェクト化することができる
- Procオブジェクトをメソッドの引数に渡すことができ、ブロックとして渡す場合は引数の前に「&」を付ける(メソッドには一つのブロックしか渡せない)
- Procオブジェクトは、普通の変数としてメソッドの引数に渡すこともできる
- Procオブジェクトは、「->」(ラムダリテラル)または「lambda」メソッドを使っても作成できる
- Procとラムダの違いは、ラムダは引数に厳密なことと、Procやラムダの内部でreturnやbreakを使った場合に挙動が異ること
- ブロックに引数を渡す場合、ラムダは引数に過不足があるとエラーになる
- returnの場合、Procではメソッドを抜けるがラムダはメソッドを抜けない
- breakの場合は、Procではエラーになるがラムダはエラーにならない
- 関連記事
Tomoyuki
最新記事 by Tomoyuki (全て見る)
- 【スト6】モダンキャミィの初心者向けコンボまとめ【STREET FIGHTER 6(ストリートファイター6)】 - 2024年11月10日
- モンハンワイルズでおすすめのオプション設定まとめ【Monster Hunter Wilds】 - 2024年11月4日
- モンハンワイルズでおすすめのグラフィック設定まとめ【Monster Hunter Wilds】 - 2024年11月2日
コメントを残す