loading...

Ruby Blocks: Do-end vs. Braces

mudasobwa profile image Aleksei Matiushkin Originally published at rocket-science.ru on ・2 min read

Ruby tries to add a spoon of sugar to each damn line of your code any time she thinks it to be possible. That’s nice. Sometimes she became meddlesome. That used to drive me bonkers. A newbie is to be that rara avis, to understand that there is actually a huge difference between braces and do-end constructs to define a block.

Well, everybody may spend a life successfully writing tons lines of ruby code and never get stuck in weird exceptions, coming from 3rd party libs, which in a case were induced by negligent mess between {} and do-end in domestic code. Let’s digress from our dramatic story and take a look at the following snippet. Somebody was set bringing benchmarks to an application running at a snail’s pace. Well, the task looks straightforward. Install benchmark gem, read the documentation, try an example:

require 'benchmark'
puts Benchmark.measure { "a"*1_000_000 }

Works fine! Let’s try smth more complicated:

require 'benchmark'
puts Benchmark.measure do
  while true
    print 'a'
    break if Random.rand(100) === 1
  end
end

Ooooups…

irb:010 >
# LocalJumpError: no block given (yield)
# from IRRELEVANT_PATH_TO_RVM/lib/ruby/2.0.0/benchmark.rb:281:in `measure'
# from (irb):9`

WTF? That’s the syntax sugar, ruby mixed into your tea. That’s a time to take a look at an operator precedence table.{} binds tighter than do-end. Furthermore, do-end clause has the lowest precedence at all. In other words, the latter codepiece is similar to:

require 'benchmark'
(puts Benchmark.measure) do
  # irrelevant code
end

Surely, the aforementioned hitch never befuddled a guru, but there is a style guideline which may get rid of the possibility even to stuck with this. Use braces {} when a block returns a value. Use do-end clause otherwise.

Posted on Dec 25 '18 by:

mudasobwa profile

Aleksei Matiushkin

@mudasobwa

NB! I am _not_ a member of #DEVCommunity. → I like: Elixir, Erlang, Ruby, R, C, COBOL. → I hate: Apple, JS, Rails, haters. → I am more functional, than object oriented.

Discussion

markdown guide