不,它并不是这样的。作为Ruby的一般规则,如果两个东西看起来相似,那么它们之间肯定存在微妙的差别,使得它们各自独特且必要。
{
和
}
并不总是扮演块分隔符的角色。当它们不扮演块分隔符的角色时(例如构建哈希时,
{ a: 1, b: 2 }
),它们不能被
do
...
end
替代。但是当花括号确实用于分隔块时,它们几乎总是可以被
do
...
end
替代。但要小心,因为有时候这可能会改变你语句的含义。这是因为
{
...
}
的优先级更高,它们比
do
...
end
绑定更紧密。
puts [ 1, 2, 3 ].map { |e| e + 1 }
2
3
4
puts [ 1, 2, 3 ].map do |e| e + 1 end
#<Enumerator:0x0000010a06d140>
就相反的情况而言,
do
...
end
在作为块分隔符的角色中,并不总是可以被花括号替代。
[ 1, 2, 3 ].each_with_object [] do |e, obj| obj << e.to_s end
[ 1, 2, 3 ].each_with_object [] { |e, obj| obj << e.to_s }
在这种情况下,您需要将有序参数放在括号中:
[ 1, 2, 3 ].each_with_object( [] ) { |e, obj| obj << e.to_s } # valid with ( )
这些句法规则的结果是你可以写成这样:
[ 1, 2, 3 ].each_with_object [ nil ].map { 42 } do |e, o| o << e end
而且上述还展示了一种情况,即
{}
不能被
do
/
end
替代的情况:
[ 1, 2, 3 ].each_with_object [ nil ].map do 42 end do |e, o| o << e end
Lambda语法中的
->
稍有不同,它可以同时接受以下两种形式:
foo = -> x do x + 42 end
foo = -> x { x + 42 }
此外,
do
和
end
本身并不总是限定一个块。特别是,这个
for x in [ 1, 2, 3 ] do
puts x
end
这个
x = 3
while x > 0 do
x -= 1
end
这个
x = 3
until x == 0 do
x -= 1
end
表面上包含了
do
...
end
关键字,但它们之间没有真正的代码块。它们内部的代码并不引入新的作用域,只是用来重复几个语句的语法。在这里不能使用花括号,并且可以省略
do
而编写语法,例如:
for x in [ 1, 2, 3 ]
puts x
end
无论是
{
...
}
还是
do
...
end
作为定界符都可以互换使用的情况,选择使用哪种取决于编程风格,并且
在另一个问题中广泛讨论(我在这里的一个例子中引用了那里被接受的答案)。在这种情况下,我个人更倾向于强调可读性而不是严格的规则。
do
...end
和{
...}
是否可以互换使用,以及何时可以互换。你链接的那个问题则关注风格,它询问在可互换时应该使用哪一个。 - Boris Stitnicky