在Ruby中有两种不同的写块语法。有
do |something| ... end
还有
{ |something| ... }
我意识到这只是用括号替换关键字“do”和“end”。这让我想知道,当Ruby使用这两种语法时,它处理它们的方式是否有任何显着差异。还是Ruby以相同的方式处理它们,可以互换?如果它们是完全可互换的,那么为什么要包括两者呢?
ogsagwnx1#
不,不是的。作为Ruby的一般规则,如果两个东西看起来很像,你可以打赌它们之间有一个微妙的差异,这使得它们中的每一个都是独特的和必要的。{和}并不总是充当块分隔符的角色。当它们不充当块分隔符的角色时(例如在构造散列时,{ a: 1, b: 2 }),它们不能被do... end。但是当花括号确实分隔一个块时,它们几乎总是可以被do所取代。end。但是要小心,因为有时这会改变你陈述的意思。因为{... }具有更高的优先级,它们比do绑定得更紧…end:
{
}
{ a: 1, b: 2 }
do
end
puts [ 1, 2, 3 ].map { |e| e + 1 } # { ... } bind with #map method 2 3 4 #=> nil puts [ 1, 2, 3 ].map do |e| e + 1 end # do ... end bind with #puts method #<Enumerator:0x0000010a06d140> #=> nil
至于相反的情况,do…end作为块分隔符的角色不能总是用花括号代替。
[ 1, 2, 3 ].each_with_object [] do |e, obj| obj << e.to_s end # is possible [ 1, 2, 3 ].each_with_object [] { |e, obj| obj << e.to_s } # invalid syntax
在这种情况下,必须将有序参数加括号:
[ 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 #=> [ 42, 1, 2, 3 ]
上面还演示了{}不能被do/end替换的情况:
{}
[ 1, 2, 3 ].each_with_object [ nil ].map do 42 end do |e, o| o << e end #=> SyntaxError
->的Lambda语法略有不同,因为它同样接受两者:
->
foo = -> x do x + 42 end # valid foo = -> x { x + 42 } # also valid
此外,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
表面含有doend关键字,但它们之间没有真实的的块。它们内部的代码并没有引入新的作用域,它只是用来重复几个语句的语法。这里不能使用大括号,语法可以不使用do,例如:
for x in [ 1, 2, 3 ] puts x end # same for while and until
对于{... }和do…end分隔符是可互换的,选择使用哪一个是编程风格的问题,是extensively discussed in another question(我在这里引用了一个我的例子)。在这种情况下,我个人倾向于强调可读性而不是僵化的规则。
uxh89sit2#
通常,{ }块语法用于单行块,而do ... end语法用于多行块。两者之间的一个区别是,对于花括号块,参数必须在括号内。示例:some_method(param1, param2) { ... }
{ }
do ... end
some_method(param1, param2) { ... }
some_method param1, param2 do ... end
2条答案
按热度按时间ogsagwnx1#
不,不是的。作为Ruby的一般规则,如果两个东西看起来很像,你可以打赌它们之间有一个微妙的差异,这使得它们中的每一个都是独特的和必要的。
{
和}
并不总是充当块分隔符的角色。当它们不充当块分隔符的角色时(例如在构造散列时,{ a: 1, b: 2 }
),它们不能被do
...end
。但是当花括号确实分隔一个块时,它们几乎总是可以被do
所取代。end
。但是要小心,因为有时这会改变你陈述的意思。因为{
...}
具有更高的优先级,它们比do
绑定得更紧…end
:至于相反的情况,
do
…end
作为块分隔符的角色不能总是用花括号代替。在这种情况下,必须将有序参数加括号:
这些语法规则的结果是,你可以这样写:
上面还演示了
{}
不能被do
/end
替换的情况:->
的Lambda语法略有不同,因为它同样接受两者:此外,
do
和end
本身并不总是划分块。特别是,这个还有这个
还有这个
表面含有
do
end
关键字,但它们之间没有真实的的块。它们内部的代码并没有引入新的作用域,它只是用来重复几个语句的语法。这里不能使用大括号,语法可以不使用do
,例如:对于
{
...}
和do
…end
分隔符是可互换的,选择使用哪一个是编程风格的问题,是extensively discussed in another question(我在这里引用了一个我的例子)。在这种情况下,我个人倾向于强调可读性而不是僵化的规则。uxh89sit2#
通常,
{ }
块语法用于单行块,而do ... end
语法用于多行块。两者之间的一个区别是,对于花括号块,参数必须在括号内。示例:some_method(param1, param2) { ... }