What is the difference or value of these block coding styles in Ruby?
Asked Answered
J

7

34

Which style is preferred? Is there a good reason for one vs. the other?

Thanks in advance!

1) cmds.each do |cmd|
   end

2) cmds.each { |cmd|
   }

Example code:

cmds = [ "create", "update", "list", "help" ]

# Block style one
#
cmds.each do |cmd|
  puts "loop1, cmd: #{cmd}"
end

# Block style two
#
cmds.each { |cmd|
  puts "loop2, cmd: #{cmd}"
}
Joshuajoshuah answered 10/2, 2009 at 16:21 Comment(4)
there is no difference, the do/end one is just nicer. also i corrected your questionLasko
Thanks Iraimbilanja, your changes make sense to me.Joshuajoshuah
@Iraimbilanja: There is a difference, as described in the answers.Shanghai
See also: https://mcmap.net/q/138943/-different-behaviour-of-39-do-end-39-and-quot-quot-block-in-ruby-duplicateGringo
P
40

The rails team and many other rubyists prefer to use curly braces for one line blocks and do...end for multi-line ones.

The only functional difference between the two is that the precedence of a do...end block is lower than that of a {...} block.

Pigpen answered 10/2, 2009 at 16:25 Comment(1)
They are the same thing though. So when using braces, you would write it on one line like: cmds.each { |cmd| puts "loop2, cmd: #{cmd}" }Cantu
W
23

According to the "Pickaxe" book (I'm looking at the 2nd edition here), Gordon's correct: the only difference is precedence:

p.356 (my italics) :

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.

See also p.168 for an example.

Wellborn answered 10/2, 2009 at 17:9 Comment(0)
C
13

The two forms are equivalent.

The recommended style is to use the braces for one line blocks and use the "do"-"end" for multiline blocks.

Edit: Austin Ziegler pointed out (in the comment below) that the two forms have difference precedence levels: Curly braces have higher precedence. Therefore, when calling a method without parenthesis a block enclosed in {} will bind to the last argument instead of the calling method.

The following example was suggested by Austin:

def foo
    yield
end

puts foo { "hello" }

puts foo do
    "hello"
end

The first "puts" prints "hello": foo gets called returning "hello" which is the argument to puts.

The second bails with an error:

in `foo': no block given

Since in this case the do-end block binds to the puts method.

Thanks again to Austin for clearing this up.

Comfrey answered 10/2, 2009 at 16:28 Comment(2)
No, they're not. def foo yield end puts foo { "hello" } puts foo do; "hello"; end The latter will throw an exception. The former will not (and it will print "hello"). { } binds to #foo; do/end binds to #puts.Sulfate
Thanks for pointing this out. I have edited the answer giving you the credit. You should have really added your own answer so that the original poster could mark it as the correct answer.Comfrey
P
12

Gordon's answer is "the Ruby Way," and although it is a common practice to put one line in braces, it is not required.

Also note the ease with which one can act on the resulting value:

cmds.each do |cmd| cmd.upcase! end.sort

# Now, cmds = ["CREATE", "HELP", "LIST", "UPDATE"]

Although you might already see how {} is more readable here, and therefore preferred if anyone else is going to see your code:

cmds.each { |cmd| cmd.upcase! }.sort
Peursem answered 10/2, 2009 at 16:57 Comment(1)
zandev, Thanks for the extra tip on 'end.sort'Joshuajoshuah
C
3

Most often, style 1 is used for multiple-line blocks and style 2 is used for one-liners.

The do…end syntax closely resembles other Ruby control structures (if, def, class), so using that for blocks keeps the appearance of your code consistent and clear. But it doesn't work well for one-liners, which is why the brackets version is preferred there.

Chickabiddy answered 10/2, 2009 at 16:31 Comment(0)
V
1

I don't think it really matters - it's just an aesthetic personal choice. Some people prefer to use the do...end version when the block needs multiple lines and the {...} version when its all on one line.

Vanillic answered 10/2, 2009 at 16:27 Comment(0)
D
1

Conventionally, using {} is reserved for single-line blocks, while do...end is for multi-line blocks.

Because of how {} are not used in Ruby as often as in other languages like C++ or Javascript, using do...end when given the chance instead of {} can help make your code more readable for other Rubyists.

Note that {} has precedence over do...end.

Dairyman answered 23/7, 2015 at 21:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.