Wednesday, April 11, 2007

Understanding blocks in Ruby...

Blocks in Ruby.

I am trying to learn Ruby, because I am working on a Rails project. If one browses around for Ruby literature on the web, one often finds a common thing - 'Blocks are the best part of Ruby'. I have often used them while trying to do something.find { do stuff } . But never really appreciated what they were, till I decided to solve that mystery. If one googles 'ruby blocks', one finds typical examples illustrating how they are used, but not necessarily why and how they should be used. This sort of confused me to a greater degree. Basically, after spending a good couple of hours, I realized what blocks are how they are used and what is similarity difference between ruby blocks and python lambda?


1. Blocks are typically executed with an iterator -

Basically, a block is a piece of code which is enclosed between a '{' and '}' and follows immediately following a method call. Typically one would find

myarray.each {|x| p x;}


'each' is basically an 'iterator' over an Array object. Ok so what is an 'iterator' - is a method that invokes block of code repeatedly. Thus first use of 'blocks' is - they can be used to pass random code to an 'iterator' and that gets executed. But then what is the big deal about it? Well basically at first sight, one doesn't quite appreciate this. But consider -
- Find the square of each number in the array
- Find a list of all numbers in an array that is divisible by three

Now to solve the two problems ordinarily one would require two methods 'do_square' and 'is_divisible_by_3', but 'blocks' make it much simpler. Just pass a different code block to the 'each' methord.

2. Blocks can be used for 'transactional use'.

A very common example of this is code like

File.open('foo.txt', 'r') do |afile|
while ( s = afile.gets)
p s
end
end


At first sight, this might appear like another use of 'iterator' an iterator oer lines of a file. But this is not strictly true.

the 'open' function of a File class (note not Object) 'yield's the block above. Thus actually the whole of while (s = ...) code is getting executed in the File.open function itself. Sounds a bit un-intuitive. Ok.. So what's the big deal again? Well this takes care of Opening and Closing the file when done automatically in case the user forgets to do so.

3. Blocks can be used to create 'Proc' objects

This use of ruby blocks is like 'python lambda'. Though ruby blocks are far more flexible than python lambda as python lambda allows you only a single line of code.
consider this


def foo(x)
return proc { |y| x+y;}
end

p = foo(2)

p.call(2) = 4
p.call(2000) = 2002

I haven't really used this form of blocks yet. So can't comment about where this can be useful.

Actually a lot of what I have understood can be found on this page of ruby book.

No comments: