ブロックでのnext、break、returnの動作

配列の項目を列挙するeachや、文字列の置換を行うsubなどのメソッドに渡すブロックにおいて、next、break、returnの制御文が及ぼす作用を理解するのは少し難しい。
先日、String::subに渡したブロック内でbreakを使ったために思わぬ動作となり、何が起きているのか分からない状態に陥った。
そこで調べたことを以下にまとめる。

ブロックでnextを実行すると…

nextに与えた値がブロックの戻り値となって、ブロックを呼び出したメソッドに返る。

def func
    s = "abcdefg".sub(/cde/) { |m| next "123" }
    puts "sub:#{s}\n"
    return "xyz"
end

puts "next in block for String::sub\n"
puts "func:#{func}\n"

 ↓

next in block for String::sub
sub:ab123fg
func:xyz

ブロックでbreakを実行すると…

breakに与えた値がブロックを呼び出したメソッドの値となって、そのメソッドの呼び出し元に返る。

def func
    s = "abcdefg".sub(/cde/) { |m| break "123" }
    puts "sub:#{s}\n"
    return "xyz"
end

puts "break in block for String::sub\n"
puts "func:#{func}\n"

 ↓

break in block for String::sub
sub:123
func:xyz

ブロックでreturnを実行すると…

returnに与えた値がブロックを呼び出したメソッドの呼び出し元の値として返る。

def func
    s = "abcdefg".sub(/cde/) { |m| return "123" }
    puts "sub:#{s}\n"
    return "xyz"
end

puts "return in block for String::sub\n"
puts "func:#{func}\n"

 ↓

return in block for String::sub
func:123