views:

257

answers:

2

New to ruby, put on your newbie gloves.

Is there any difference (obscure or practical) between the following two snippets?

my_array = [:uno, :dos, :tres]
my_array.each { |item| 
    puts item
}

my_array = [:uno, :dos, :tres]
my_array.each do |item| 
    puts item
end

I realize the bracket syntax would allow you to place the block on one line

my_array.each { |item| puts item }

but outside of that are there any compelling reasons to use one syntax over the other?

+16  A: 

Ruby cookbook says bracket syntax has higher precedence order than do..end

Keep in mind that the bracket syntax has a higher precedence than the do..end syntax. Consider the following two snippets of code:

1.upto 3 do |x|
  puts x
end

1.upto 3 { |x| puts x }
# SyntaxError: compile error

Second example only works when parentheses is used, 1.upto(3) { |x| puts x }

S.Mark
Ah, got it. So because of the precedence order, when you use do, you're passing the block as an additional parameter, but when you use the brackets you're passing the block as the first parameter of the results of the method invocation(s) to the left.
Alan Storm
+9  A: 

Generally the convention is to use {} when you are doing a small operation for example a method call or a comparison, etc. so this makes perfect sense

some_collection.each { |element| puts element }

But if you have slightly complex logic that goes to multiple lines then use do end like

1.upto(10) do |x|
  add_some_num = x + rand(10)
  puts '*' * add_some_num
end

Basically it comes down to, if your block logic goes to multiple lines and cannot be fitted on the same line then use 'do end' and if your block logic is simple and just a simple/single line of code then use {}.

nas
I agree with using do/end for multi-line blocks, but I will go with braces if I'm chaining additional methods to the end of the block. Stylistically I like {...}.method().method() over do...end.method().method, but that might just be me.
Greg
Agreed, although I prefer to assign the result of a method with block to a meaningful variable and then call another method on it like `result_with_some_condition = method{|c| c.do_something || whateever}; result_with_some_condition.another_method` as that just makes it a bit more easily understandable. But generally I would avoid a train wreck.
nas