Ruby Style: Ruby do ... end versus {}

Posted by joe Thursday, June 28, 2007 01:59:00 GMT

I’m lucky enough to be pairing with Jim Weirich and I’m learning a ton. Of course I’m learning things like how to get the most out of the one true editor and the really hard to understand ins and outs of Ruby.

What I’m enjoying the most is the different perspective on developing in Ruby. We’ve had quite a few discussions about style. The most recent I thought I would put up here.

One or more lines

When you come to Ruby people inevitably ask the question of when to use do … end and when to use the {} syntax for blocks. The normal answer, and the one I’ve subscribed to, is that you use {} if you are on one line, and do … end if you span more than one line.


  Items.find(:all).each { |item| puts item.description }

  Items.find(:all).each do |item|
    # do something
    # do something else
    item.save
  end

Problems with this approach

First, when you decide to add more functionality into your block, you have to change the surrounding syntax. If you are following Red, Green Refactor, this could happen quite frequently.

The most interesting issue we discussed was that this style tells you nothing of value when you are reading the code. We can tell visually that it’s one or two lines.

Use {} when returning a value, do … end when performing actions

The alternative is to use these two syntaxes to communicate what you are doing. Jim’s style of development, which I’m quickly growing more fond of, is to use {} when you are returning a value from a block.


  [1,3,4,5,6].find { |i| i == 4 }

  [1,3,4,5,6].collect { |i| i.to_s }

On the flip side use the do … end syntax when performing actions, but not returning any values.


  %w{ one two three four five }.each do |i| i.capitalize! end

  %w{ one two three four five }.each do |i| 
    i.capitalize!
    i.reverse!
  end

So now when you are glancing through some code and you see a block that looks like this:


  array.method_accepting_block { |item| 
    some_action
    more_actions
  }

you will know that they are returning a value at a glance.

Interesting idea. Thoughts?

Comments

Leave a response

  1. Chad HumphriesJune 28, 2007 @ 12:03 PM
    I would usually just opt for the returning (k-combinator) when returning a value (versus {}). <table class='CodeRay'><tr> <td title='click to toggle' class='line_numbers' onclick='with (this.firstChild.style) { display = (display == \'\') ? \'none\' : \'\' }'>
    1
    2
    3
    4
    
    </td> <td class='code'>
     returning GetYourItemHere.new do |item|
         some_action
         more_actions
     end
    </td> </tr></table>
  2. Ken BarkerJune 28, 2007 @ 12:28 PM
    Joe, your link is broken. Here is the real "link":http://vim.org.
  3. NickJune 28, 2007 @ 12:28 PM
    I think you mislinked "one true editor":http://www.vim.org/
  4. JoshJune 28, 2007 @ 06:28 PM
    Hey Joe, I think I found a cool distance collaboration tool, it's based on the Obby protocol, and works in the ONE TRUE EDITOR. :) Basically, 2 people could site in 2 locations and each person would be able to edit the file real-time. With emacs' buffer support, I would think that you could edit as many files as you needed in one editor. Seems to have active development, last commit was the 16th of June. http://dev.technomancy.us/index.cgi/wiki/ebby
  5. Dan MangesJune 29, 2007 @ 07:55 PM
    I like hearing about an alternative since I've always used do/end for multiple lines and {} for inline blocks. I'll have to try it before I can decide which one I like better. :-)
  6. JoeJune 30, 2007 @ 01:40 AM
    @Nick & Ken: Easy to beat on something you haven't tried. Come over to the dark side, you'll like it more than you realize :-) @Chad: That is not necessarily what I'm talking about. That would not work for array.find {|i| i = 'something' } @Josh Actually screen with emacs works amazingly well, and saves enough bandwidth that we can do video Skype without much interruption. It's great.
  7. Josh GJuly 03, 2007 @ 12:05 AM

    Joe, I am still mystified why the end…do exists at all as it grates against the other terseness facilities of Ruby, but then so does the underscored variable names convention (as opposed to lowCamelCased ones).

    As for using {} only when returning a value, doesn’t every statement return a value (in your example, the array with it’s elements capitalised and reversed)?