Ruby Blocks 101

January 20, 2006 at 1:00 am 25 comments

One of the difficulties you might have with jumping into Ruby on Rails is that you need to learn the Ruby language (yes, you do 😉 ). And if you come from the PHP background as I am, the single weirdest thing in Ruby would be the notion of blocks. I have never seen the blocks in any other language. The concept seems beautiful, but completely unrelated to anything I know about programming.

The concept of blocks is logical and intuitive, but most likely very different from the way you experienced programming. Blocks are like alien logic – something so basic, that it changes the meaning of everything. Think of how an amphibian race of super-intellectual beings would differ from humans – this is how different the blocks concept is from your PHP functions.

As blocks are the basic structures of Ruby, chances are you have already seen them and did not really understand what was going on. I hope this post will be able to help you out with getting the hang of the concept really quickly.

So let’s start with an easy example. Run irb (cmd irb.bat) and define the method:

def aliens
i = 1
j = 2
yield(i, j)
end

This method just assigns two variables and then passes those variables to the block. Now let’s call the block:

aliens { |x, y| puts x, y }

It works as follows: aliens method is called, with Ruby recognizing that this method has a block attached to it. Once the yield is encountered within the aliens, it is passed to the block together with any parameters in the brackets. As i and j are local variables, we need to define the first and second variable to be used to hold i and j values. Finally we have the Ruby code that does something with those parameters. Puts just displays the values of i and j on screen. But you can do something more complicated:

aliens { |x, y| puts x+y*y }

This should display 5.

If you are not confused at this moment, great – you have almost mastered the blocks ;). If you are, think about the aliens as a function that allows three parameters – x, y and some arbitrarily complex Ruby code. Yield is the place where this code is executed. To make sure that this is the case, try this: (copy the code, save it to blocks.rb in your project directory and run ruby blocks.rb)

def aliens
i = 1
j = 2
yield(i, j)
i = “magick”
return nil
end

aliens { |x, y| puts x }

The script should print “1”. This is easy stuff. (Pedantic note. You can ignore “return nil“, it is there because Ruby returns the last value in the function (=method) as the result of the function, so if you run the code above in irb without “return nil”, you will see that aliens actually returns “magick”)

Another cool feature is the ability to test whether the method has a block. Check out this code:

def aliens
if block_given?
  i = 1
  j = 2
  yield(i, j)
 else puts “magick”
 end
end

aliens { |x, y| puts x }
aliens

In that case if the block is provided to the method, we execute the if statement, otherwise we execute the else statement. So, as a result the script should print “1” and “magick”.

How cool is that? 🙂

Updated in 2009:

Now that you know how blocks work, I would like to give you some implications for working with them in Ruby and Rails:

1 – It’s up to a method (or to method’s author) to have or not have a support for a block. If in the code above for method aliens there was no yield method, the block would just be ignored. If however, the yield is there and blockgiven? is not checked, you will receive an error – no block given on yield. A block is not a feature that you can use for any method any time with any parameters you can imagine. If a programmer thought of such a use for a block, you will have it, if he didn’t – you’re out of luck.

2 – It is up to the caller to understand what sort of blocks can be attached to a method. In the aliens example above, if you would try and call aliens { |x, y, z| puts x, y, z }, you will get the first two variables and nil for the third, and there will be no warning that you tried to get a variable (z), that is not really being passed (BUT – if you would try the other way round by having a block with only one variable x, Ruby will warn you and assign the merged value to a single variable x).

Also, consider an example when the information yielded is not really interchangeable. Let’s say that from my method I do an yield(x,y,zoom) for drawing a map. In my block I need to understand the correct sequence of variables in the yield and assign them correctly in my block. The only way to understand it is by looking up a documentation for this method, or sometimes more brutally – by going into the code and looking at the yield call.

Summary

So, what does this mean? This means, that blocks and yields are not magical, although they might seem so.It also means that sometimes in Rails it is very hard to understand which methods will accept a block and for those that accept the block what is the information passed to the block. However, usually there are no more than 2 variables being passed to a block, and you get used to working with the methods that way.

Hope it helps 😉

Entry filed under: Uncategorized.

Another good introduction article from Curt Hibbs Building a user authorization system in PHP – part I

25 Comments Add your own

  • 1. Wilhelm Tell  |  January 20, 2006 at 5:59 am

    If you programmed in C++ before, then chances are that you’ve seen blocks before.

    The analog of Ruby’s block in C++ is the STL iterator. The beauty about Ruby is that blocks are part of the language, wherease in C++ iterators are ready for use only for the STL; for a completely custom-made class you’d probably need to create a custom-made iterator.

    Then again, one may claim that the beauty about C++ is that the syntax is simple, and anything that is more complex can be created by the user.

    Reply
  • 2. prerona  |  February 4, 2006 at 2:17 pm

    interesting. thanks for the visit

    Reply
  • 3. michalkuklis.com Blog » Blog Archive » ruby way huh?  |  March 31, 2006 at 4:51 am

    […] Ruby is beautiful and very powerful.  In order to start using it you have to understand how some things work.  What was  ne w for me  are :symbols and  blocks.  Metaprogramming is  also  something to be aware of. […]

    Reply
  • 4. Efrén  |  April 6, 2006 at 2:50 pm

    We noticed that your blog have some Ruby On Rails releated content, and that
    is why we would like to invite you to register yourself and your
    blog at RubyCorner, a directory of Ruby related blogs:

    http://www.rubycorner.com/

    We like to think about RubyCorner as a “meeting place” for the
    community, also as a “focal point” where the people new to this
    technology can quickly tune into the pulse of the community.
    Registering your blog will help build a valuable resource for
    this growing community.

    Reply
  • 5. tma  |  August 7, 2006 at 12:13 pm

    thanks for this really easy introduction to blocks 🙂

    Reply
  • 6. David  |  September 5, 2006 at 7:28 am

    Thanks for taking the time to post this. Immediately after reading your first example I got it! Coming from PHP it’s taking a little time to understand certain Ruby concepts I’ve never been exposed to before.

    Reply
  • 7. yunus  |  February 2, 2007 at 2:23 am

    Great!
    Thanks for expainig yeild.
    You explained really amazingly. I understand it and infact I mastered it by
    reading your explaination.

    thanks
    Yunus

    Reply
  • 8. Tim  |  April 8, 2007 at 6:52 pm

    yay, now I finally know what the heck blocks are!

    Reply
  • 9. EstadoBeta » Archivo » Ruby  |  August 6, 2007 at 5:35 am

    […] “@productos”. ¿Qué es eso de “yield”? Es algo que tiene que ver con los bloques en Ruby (lo que va entre los corchetes), pero eso lo podemos ver en otro artículo. La ventaja es […]

    Reply
  • 10. Douglas  |  August 30, 2007 at 6:31 pm

    Yes!! Finally an explanation I understand. I have struggled with this concept for a while. Thank you.

    Reply
  • 11. Douglas  |  August 30, 2007 at 6:34 pm

    This one also helped… http://www.artima.com/intv/closures.html
    Matz describes it as a nameless function passed into another function.

    Reply
  • 12. My Blog » Blog Archive » Ruby Blocks  |  August 30, 2007 at 6:37 pm

    […] Blog post Sample… […]

    Reply
  • 13. van  |  September 16, 2007 at 1:34 am

    Thank you very much.e

    Reply
  • 14. Robert  |  December 4, 2007 at 12:25 am

    Hey, fantastic job. I now actually understand how to make methods that use blocks.

    However, damn you at the same time. I have started rewriting my methods now to take advantage of this new found knowledge 🙂

    Seriously though, thanks.

    Reply
  • 15. Jonathan  |  December 14, 2007 at 11:43 pm

    Actually functors are the C/C++ equivalent and not iterators. It isn’t possible to customize the logic executed per iteration using STL iterators alone. You have to combine iterators with functors to get closure/block behavior. (And, in C#, anonymous delegates do the job).

    Reply
  • 16. Adam  |  June 16, 2008 at 5:46 pm

    Blocks are essentially lambda expressions, you’ll have the pleasure of using higher-order functions in any functional language you touch.

    Reply
  • 17. matt  |  December 3, 2008 at 10:45 pm

    Hi,

    It might be useful to include a ‘real world’ example of how this sort of thing can be used. I understand the concept but can’t immediately see why I would want to do it (poor imagination on my part perhaps.)

    matt

    Reply
  • 18. James Gardner  |  January 22, 2009 at 9:46 am

    I agree with Matt. Some practical application of where blocks might be used would be really useful. Though by no great stretch of the imagination I can easily think of some myself just from reading your article.

    Thanks very much.

    Reply
  • […] 12. curly brackets { } – these are most of the time an indicator of a block. More on blocks here. […]

    Reply
  • 20. freedumb2000  |  December 4, 2009 at 10:57 pm

    This is probably the first time that I actually managed to understand blocks. Thanks!

    Reply
  • 21. Straight Thinking » Blog Archive » Streaming XML with Rails  |  December 11, 2009 at 7:26 pm

    […] Block to render the output (this post is a nice […]

    Reply
  • 22. pakalk  |  April 3, 2010 at 10:08 am

    why is it better than for..in loop?

    Reply
  • 23. akanksha  |  June 7, 2010 at 3:30 pm

    gud 1… really helpful:)

    Reply
  • 24. Like Ruby’s blocks? Use ‘em in Objective-C too!  |  March 2, 2011 at 10:54 am

    […] Ruby 101 about Ruby blocks […]

    Reply
  • 25. mma  |  September 4, 2014 at 2:42 pm

    Do you have any video of that? I’d love to find out more details.

    Reply

Leave a reply to Jonathan Cancel reply

Trackback this post  |  Subscribe to the comments via RSS Feed


Starting to learn Rails?

Kindle

Get Kindle - the best e-book reader, that I personally use, and the only one that you can read on the beach - very useful: Kindle Wireless Reading Device (6" Display, Global Wireless, Latest Generation)