{ } と do end の違い

Benchmark を使うときに

require 'benchmark'

puts Benchmark::CAPTION
puts Benchmark.measure {
  a = [1, 2, 3]
  a.replace [4, 5, 6]
}

このように { } を使うのは OK なのに


{ } を do end に変えると

require 'benchmark'

puts Benchmark::CAPTION
puts Benchmark.measure do
  a = [1, 2, 3]
  a.replace [4, 5, 6]
end
`measure': no block given (LocalJumpError)

ってエラーが出る。
{ } と do end って同じものだと思っていたけど何か違うみたいだ。

do...endと {...}で動作が異なる場合があります。

foobar a, b do .. end # foobar がブロック付きメソッドとして呼び出されます
foobar a, b { .. }    # b がブロック付きメソッドとして呼び出されます

これは{ }の方がdoブロックよりも結合強度が強いためです。

プログラミング言語 Ruby リファレンスマニュアル

どうやら結合強度が違うらしい。
ふむ。するってーとなんだい
さっきの Benchmark のスクリプトだと

puts Benchmark.measure {
  a = [1, 2, 3]
  a.replace [4, 5, 6]
}

では Benchmark.measure に { } が渡されるのに

puts Benchmark.measure do
  a = [1, 2, 3]
  a.replace [4, 5, 6]
end

これだと puts に do end が渡されるってことになるのかな?


試しに puts を除いてみる。

Benchmark.measure do
  a = [1, 2, 3]
  a.replace [4, 5, 6]
end

エラーが出なくなった。


あーそうか。

`measure': no block given (LocalJumpError)

って「measure にブロックが渡されてません」ってことか。

Benchmark.measure

だと同じエラーになった。納得。
do end を使った場合、Benchmark.measure にブロックが渡されていないのは間違いないようだ。
きっと puts に渡されているんですね。


ところで、LocalJumpError ってなんぞ?と気になったので
LocalJumpError - Rubyリファレンスマニュアル
を少し読んでみたのだけどよく分からなかった。

スコープを出てしまった Proc からの return, break, retry で発生します。

って説明があるんだけどなんで上記の Benchmark のスクリプト
このエラーが発生するのかよく分からない。