What is the difference or value of these block cod

2019-01-01 13:47发布

问题:

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}\"
}

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

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


回答5:

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.



回答6:

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.



回答7:

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.