Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

do..end vs curly braces for blocks in Ruby

People also ask

Do-end blocks Ruby?

There are two ways of defining a block in Ruby: The first is using the do.. end keyword, the other is using a pair of curly braces. Do.. end block is mainly used when defining a block of code that spans multiple lines, while curly braces {} are used when defining a block of code that spans a single line.

When to use do-end in Ruby?

Ruby blocks are anonymous functions that can be passed into methods. Blocks are enclosed in a do-end statement or curly braces {}. do-end is usually used for blocks that span through multiple lines while {} is used for single line blocks. Blocks can have arguments which should be defined between two pipe | characters.

Can you use brackets in Ruby?

Nope. You need to use end instead of a } .


The general convention is to use do..end for multi-line blocks and curly braces for single line blocks, but there is also a difference between the two that can be illustrated with this example:

puts [1,2,3].map{ |k| k+1 }
2
3
4
=> nil
puts [1,2,3].map do |k| k+1; end
#<Enumerator:0x0000010a06d140>
=> nil

This means that {} has a higher precedence than do..end, so keep that in mind when deciding what you want to use.

P.S: One more example to keep in mind while you develop your preferences.

The following code:

task :rake => pre_rake_task do
  something
end

really means:

task(:rake => pre_rake_task){ something }

And this code:

task :rake => pre_rake_task {
  something
}

really means:

task :rake => (pre_rake_task { something })

So to get the actual definition that you want, with curly braces, you must do:

task(:rake => pre_rake_task) {
  something
}

Maybe using braces for parameters is something you want to do anyways, but if you don't it's probably best to use do..end in these cases to avoid this confusion.


From Programming Ruby:

Braces have a high precedence; do has a low precedence. If the method invocation has parameters that are not enclosed in parentheses, the brace form of a block will bind to the last parameter, not to the overall invocation. The do form will bind to the invocation.

So the code

f param {do_something()}

Binds the block to the param variable while the code

f param do do_something() end

Binds the block to the function f.

However this is a non-issue if you enclose function arguments in parenthesis.


There a few points of view on this, it's really a matter of personal preference. Many rubyists take the approach you do. However, two other styles that are common is to always use one or the other, or to use {} for blocks that return values, and do ... end for blocks that are executed for side effects.


There is one major benefit to curly braces - many editors have a MUCH easier time of matching them, making certain types of debugging much easier. Meanwhile, the keyword "do...end" is quite a bit harder to match, especially since "end"s also match "if"s.


The most common rule I've seen (most recently in Eloquent Ruby) is:

  • If it's a multi-line block, use do/end
  • If it's a single line block, use {}

I'm voting for do / end


The convention is do .. end for multiline and { ... } for one-liners.

But I like do .. end better, so when I have a one liner, I use do .. end anyway but format it as usual for do/end in three lines. This makes everyone happy.

  10.times do 
    puts ...
  end

One problem with { } is that it is poetry-mode-hostile (because they bind tightly to the last parameter and not the entire method call, so you must include method parens) and they just, to my mind, don't look as nice. They are not statement-groups and they clash with hash constants for readability.

Plus, I've seen enough of { } in C programs. Ruby's way, as usual, is better. There is exactly one type of if block, and you never have to go back and convert a statement into a compound-statement.


A couple influential rubyists suggest to use braces when you use the return value, and do/end when you don't.

http://talklikeaduck.denhaven2.com/2007/10/02/ruby-blocks-do-or-brace (on archive.org)

http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc (on archive.org)

This seems like a good practice in general.

I'd modify this principle a bit to say that you should avoid using do/end on a single line because it's harder to read.

You do have to be more careful using braces because it'll bind to a method's final param instead of the whole method call. Just add parentheses to avoid that.