Monday, March 8, 2010

ruby blocks

My first encounter with blocks in Ruby was in a koan, which was a black box kind of experience. I got stuck thinking of the block and the receiving function as two scopes, and under this assumption it seems that a block can return to a method *and* vice versa.

As it turns out, the block convention acts more like a run time code splicer, putting the block of code (before evaluating it) IN the method so, really, there is a shared scope between the two. It’s like you’re slipping the method a little note for what to put in the yield spot. But you can also pass the block a variable from inside the method, by writing yield(variable). It looks something like this:

def method_with_a_block
yield(parameter)
end

method_with_a_block {|parameter| parameter.do_stuff}

if you prefer a multiple-line version, you can replace the brackets with do/end (and I'll also throw in an extra surprise):
variable_outside_method = "foo"

method_with_a_block do |parameter_passed_to_block|
do_stuff_with(parameter_passed_to_block)
variable_outside_method += "bar
end

If you are accustomed to C-like languages, as I am, it can be surprising that our variable_outside_method is actually changed to "foobar" once the method call is resolved. This is because blocks have access to the context in which they are called.

Blocks are extremely expressive and useful for implementing a skeleton form of a task - in fact, enumerators in ruby (e.g. "each", "detect", "select") are implemented using blocks!

No comments:

Post a Comment