Reputation: 231
I'm trying to understand when one should code blocks implicitly or explicitly. Given the following code blocks:
Implicit
def two_times_implicit
return "No block" unless block_given?
yield
yield
end
puts two_times_implicit { print "Hello "}
puts two_times_implicit
Explicit
def two_times_explicit (&i_am_a_block)
return "No block" if i_am_a_block.nil?
i_am_a_block.call
i_am_a_block.call
end
puts two_times_explicit { puts "Hello"}
puts two_times_explicit
Is it preferable to code using one over the other? Is there a standard practice and are there instances where one would work better or differently than the other and where one would not work at all?
Upvotes: 7
Views: 1369
Reputation: 7482
Actually, according to one very interesting read, second variant is 439% slower (related thread on HackerNews).
TL;DR: Creating and passing a block via yield
is a highly optimized common case in MRI, which is handled by dedicated C function in interpreter, while passing &block
is implemented differently and has a big overhead of creating new environment and creating Proc
itself on every call.
Summing up, use &block
only if you need passing it further (for example, to a next function), or manipulate it somehow in other way. Otherwise, use yield
, since it's way faster.
Upvotes: 4
Reputation: 168101
Receiving a block via &
creates a new proc object out of the block, so from the point of view of efficiency, it is better not to use it. However, using &
generally makes it easier to define methods that may or may not take a block, and using &
, you can also handle blocks together with arguments, so it is preferred by many.
Upvotes: 6