Rubyにしては珍しく
混乱してしまうところ。
Rubyはブロックを記述する際に、その範囲を示すトークンとしてdo〜endとブレース({〜})のどちらでも使える。
メソッド呼び出し do ブロック end メソッド呼び出し { ブロック }
ブロックを表す書き方としては同じだが、両者には結合度(優先度)の違いがあるため、以下のように括弧を省略してメソッド呼出を行うと、意味が変わってしまうことがある。
- blockprior.rb
def foo(bar) if block_given? puts yield else puts bar end end bar = "バー" foo bar do "ブロック" end bar = "バー" foo bar { "ブロック" }
- 実行結果
>ruby blockprior.rb ブロック blockprior.rb:13: undefined method `bar' for main:Object (NoMethodError)
2度めのfooメソッドの呼び出し時、ブレースを使うことでブロックがbarと結合してしまい、エラーとなってしまう。
ならばdo〜endだけを使えばよいかと思えば、以下のようにブレースを使わなくてはならないケースもある。
irb(main):001:0> puts [1, 2, 3, 4, 5].inject { |a, b| a+b } 15 => nil irb(main):002:0> puts [1, 2, 3, 4, 5].inject do |a, b| a+b end LocalJumpError: no block given from (irb):2:in `inject' from (irb):2:in `each' from (irb):2:in `inject' from (irb):2
do〜endを使った場合はinjectに結合できないためにエラーになってしまう。
この辺の使い分けを意識的に出来るようにならないと初心者からは脱却できないな。