Ответ 1
Существует тонкая разница между двумя синтаксисами. { }
имеют более высокий приоритет, чем do ... end
. Таким образом, следующее будет проходить bar
и блок к методу foo
:
foo bar do ... end
в то время как следующее передает блок bar
, а результат этого - foo
:
foo bar { ... }
Итак, ваши примеры будут действовать одинаково. Однако, если вы оставили круглые скобки:
> 3.upto 9 {
puts "Hi"
}
SyntaxError: compile error
(irb):82: syntax error, unexpected '{', expecting $end
3.upto 9 {
^
from (irb):82
from :0
> 3.upto 9 do
puts "Hi"
end
Hi
Hi
Hi
Hi
Hi
Hi
Hi
=> 3
Итак, { }
с большей вероятностью поймают вас, если вы оставите скобки в Ruby, что довольно часто; по этой причине, и поскольку условия Ruby и другие конструкторы управления используют end
как разделитель, люди обычно используют do ... end
для многострочных блоков кода, которые находятся в конце инструкции.
Однако { }
часто используется в местах, где do ... end
будет громоздким, например, если вы объединяете несколько методов вместе, которые принимают блоки. Это может позволить вам написать короткие, однострочные маленькие блоки, которые могут использоваться как часть цепочки методов.
> [1,2,3].sort{|x,y| y<=>x}.map{|x| x+1}
=> [4, 3, 2]
Вот пример, иллюстрирующий эту разницу:
def foo arg
if block_given?
puts "Block given to foo"
yield arg
else
puts "No block given to foo"
arg
end
end
def bar
if block_given?
puts "Block given to bar"
yield "Yielded from bar"
else
puts "No block given to bar"
end
"Returned from bar"
end
irb(main):077:0> foo bar { |arg| puts arg }
Block given to bar
Yielded from bar
No block given to foo
=> "Returned from bar"
irb(main):078:0> foo bar do |arg| puts arg end
No block given to bar
Block given to foo
Returned from bar
=> nil