Passing code blocks to methods and debugging

I’m fairly new to Ruby, puzzling the value of:

def sub1(x)
yield 5 * x
end

sub1(2) {|y| puts 3 * y } #=> 30

… over:

def sub2(x)
y = 5 * x
puts 3 * y
end

sub2(2) #=> 30

Isn’t there the danger, with passing code blocks, that half of your
method/function/sub definition is hanging somewhere else in your code
making it difficult to keep track of exactly what it does? How can I
debug a method if I don’t know what else it’s composed of until it is
called?

gvim

Ruby will trace the source of exceptions back to either the block or the
method, so there’s no problem there.
As for as debugging, that’s down to you to modify the code by adding “p”
or “puts thing.inspect” in order to narrow down the source of an issue.

The main reason for using blocks is flexibility, and a great example is
“File.open”. If you open a file without using a block, you must remember
to close it or you risk locking access to the file.
If you use a block, then the method can handle the before and after
(opening and closing the file), while giving the caller full control
over what happens to the file in between.

On Fri, Nov 1, 2013 at 7:48 PM, gvim [email protected] wrote:

def sub2(x)
y = 5 * x
puts 3 * y
end

sub2(2) #=> 30

Isn’t there the danger, with passing code blocks, that half of your
method/function/sub definition is hanging somewhere else in your code making
it difficult to keep track of exactly what it does? How can I debug a method
if I don’t know what else it’s composed of until it is called?

But that is true for any method. Blocks are just anonymous
functions. In the same way as named functions and methods you need to
properly define what a method should do and what other methods should
do. Joel gave an example: File.open is responsible for opening and
closing the file while the block passed may do whatever it needs to do
with the open File object (e.g. writing or reading).

Another example is Array#each: it is responsible for iterating all
elements. The block passed can do whatever it needs to do with the
current element. Your piece of code would probably be badly
structured with a second method regardless whether it’s a block or
another function - as long as you want to calculate and output 35x.
If you often need to calculate 5*x then the approach with the block
might be better. But the example is really somewhat artificial.

Long time ago I wrote two blog articles which you might find helpful.
http://blog.rubybestpractices.com/posts/rklemme/001-Using_blocks_for_Robustness.html
http://blog.rubybestpractices.com/posts/rklemme/002_Writing_Block_Methods.html

Kind regards

robert