singletony singletony - 14 days ago 4
Ruby Question

Ruby - What are the differences between checking if block_given? and !block.nil?

I have a ruby method that needs to check if a block was passed to it.
A colleague is suggesting that simply checking if

block.nil?
is slightly faster in performance and works for named blocks. This is already quite annoying since he is using the named block and invoking it using
block.call
rather than
yield
which has been shown to be significantly faster, since named blocks are more easy to understand in terms of readability.

Version 1:

def named_block &block
if block.nil?
puts "No block"
else
block.call
end
end


Version 2:

def named_block &block
if !block_given?
puts "No block"
else
block.call
end
end


Benchmarking shows that version 1 is slightly faster than version 2, however a quick look at the source code seems to suggest that
block_given?
is thread safe.

What are the main differences between the two approaches? Please help me prove him wrong!

ndn ndn
Answer

First off, while a single nil? check might be faster than block_given?, capturing the block is slow. So unless you were going to capture it anyway, the performance argument is invalid.

Secondly, it's easier to understand. Whenever you see block_given?, you know exactly what is up. When you have x.nil?, you have to stop and think what x is.

Thirdly, it's an idiom. In my experience, the overwhelming majority of Ruby developers will prefer block_given?. When in Rome...

Lastly, you can keep it consistent. If you always use block_given? the problem is solved for you. If you use nil? checks, you have to have the block captured.

  • There is a performance overhead.
  • It's more verbose, something Rubyists try to avoid.
  • Naming things is one of the hardest things in programming. :) Can you think of a good name for the block Enumerable#map will get for example?
  • "Grepability" is a desirable trait for a codebase to have. If you want to find all the places where you check if you were given a block, doing nil? checks can prove difficult.