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.
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.
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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With