Ruby读的是“吗?”;“做”;及;完";与“相同的方式”;{quot;和";}";?

Ruby读的是“吗?”;“做”;及;完";与“相同的方式”;{quot;和";}";?,ruby,syntax,lambda,block,Ruby,Syntax,Lambda,Block,在Ruby中编写块有两种不同的语法。有 do |something| ... end 还有 { |something| ... } 我意识到这只是用括号替换关键字“do”和“end”。这让我想知道,当Ruby使用这两种语法时,在处理它们的方式上是否有显著的差异。或者Ruby是否以同样的方式处理它们,可以互换?如果它们是完全可互换的,那么为什么两者都包括呢?一般来说,{}块语法用于单行块,而则用于。。。结束语法用于多行块。两者之间的一个区别是,对于花括号块,参数必须位于括号内。

在Ruby中编写块有两种不同的语法。有

do |something|
    ...
end
还有

{ |something|
    ...
}

我意识到这只是用括号替换关键字“do”和“end”。这让我想知道,当Ruby使用这两种语法时,在处理它们的方式上是否有显著的差异。或者Ruby是否以同样的方式处理它们,可以互换?如果它们是完全可互换的,那么为什么两者都包括呢?

一般来说,
{}
块语法用于单行块,而
则用于。。。结束
语法用于多行块。两者之间的一个区别是,对于花括号块,参数必须位于括号内。例如:

some_方法(param1,param2){…}

some_method param1, param2 do
   ...
end

不,没有。作为Ruby的一般规则,如果两件东西看起来很相似,你可以打赌它们之间有细微的差别,这使得它们每个都是独一无二的和必要的

{
}
并不总是充当块分隔符的角色。当它们不起块分隔符的作用时(例如在构造散列时,
{a:1,b:2}
),它们不能被
do
替换<代码>结束。但是,当大括号确实界定了一个块时,它们几乎总是可以被
do
替换<代码>结束。但是要小心,因为有时候这会改变你陈述的意思。这是因为
{
..}具有更高的优先级,它们的绑定比
更紧密<代码>结束

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
[ 1, 2, 3 ].each_with_object [ nil ].map do 42 end do |e, o| o << e end
#=> SyntaxError
在这种情况下,必须将有序参数括起来:

[ 1, 2, 3 ].each_with_object( [] ) { |e, obj| obj << e.to_s }  # valid with ( )
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
还有这个

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

# same for while and until

对于
{
..
}
do
..
end
定界符可互换的情况,使用哪种定界符是编程风格的问题,并且是(我在这里举了一个示例,根据其公认的答案)。在这种情况下,我个人倾向于强调可读性而不是严格的规则。

可能重复@falsetru,这不是重复。此问题询问
do
..
end
{
..
}
是否可互换(以及何时互换)。您链接的问题与样式有关,它询问在可互换时使用哪些样式。
“123”.gsub//do|s|(s.to|i+1)。to|s end=>“234”
,但
“123”.gsub/{s|(s.to|i+1)。to|s}
会引发语法错误。另一方面,
[1,2,3]。每个对象为{u object[]{e,a{a[2,3,4]
。知道为什么吗?@CarySwoveland不知道,在块规范中也找不到它。因为Ruby解析器需要一些提示,
{
是哈希还是块的开始。Ruby解析器尝试解析
一些方法p1,p2,{…}
作为散列参数,而不是块;另一方面,它将
某些方法{…}
作为block param。谢谢你的解释,@huocp。这很有意义。哇!非常感谢你给出了这样一个经过深思熟虑的答案!我将花一些时间来消化这个问题。我可能会问几个后续问题。对于一个红宝石爱好者来说,要想弄明白这一切需要时间。