美好的一天。 我对同一代码块的行为不同,具体取决于块语法大括号或do / end的类型。跳过do / end的块而没有任何错误通知:
带有大括号的块仅实现,p
打印one Ruby is a COOL language!
:
p "rubyisacoollanguage".gsub(/(ruby)(is)(a)(cool)(language)/) {
"one " + $1.capitalize + " %s %s %s %s!" % [$2,$3,$4.upcase,$5]
}
do / end中的“相同”代码段刚刚被跳过,p
向我展示Enumerator
<Enumerator: "rubyisacoollanguage":gsub(/(ruby)(is)(a)(cool)(language)/)>
:
p "rubyisacoollanguage".gsub(/(ruby)(is)(a)(cool)(language)/) do
"two " + $1.capitalize + " %s %s %s %s!" % [$2,$3,$4.upcase,$5]
end
我认为它是由于p
而发生的,在第二种情况下它消除了障碍。当我在块中添加p
时,事情就会变得很清楚。第一个块的数据打印了2次,而第二个块的数据根本没有打印。
p "rubyisacoollanguage".gsub(/(ruby)(is)(a)(cool)(language)/) {
p "one " + $1.capitalize + " %s %s %s %s!" % [$2,$3,$4.upcase,$5]
}
p "rubyisacoollanguage".gsub(/(ruby)(is)(a)(cool)(language)/) do
p "two " + $1.capitalize + " %s %s %s %s!" % [$2,$3,$4.upcase,$5]
end
对我来说,这是非常奇怪且不可预测的行为。没有错误,只需跳过部分代码。为什么会发生?
答案 0 :(得分:5)
为什么会发生?
因为{}和do / end的优先级不同。 {}是“更强”的。如“与最近的方法调用相关联”。所以这个
p foo {
something
}
这样看。
p (foo {
something
})
做/结束就是这样
p(foo) do
something
end
没有错误,只需跳过部分代码
是的,由于红宝石的另一个特征。这就是“您可以将块传递给ANY方法。然后,使用或忽略它是该方法的责任。”这里p
不需要块,只是忽略它。
答案 1 :(得分:2)
Ruby宽松的语法规则的问题在于,有时它会误解该块属于谁。由于模棱两可,p
和gsub
都可以“拥有”该块。 do
方法被分配给p
,而{ ... }
方法被固定在gsub
上。
这可能是由于某些运算符优先级类型规则所致,尽管由于该块本身不是运算符,所以我不确定现在是否可以找到该特定行为的引用。
在有歧义的地方,最好避免依赖于它的解释方式,而应更加具体:
rv = "rubyisacoollanguage".gsub(/(ruby)(is)(a)(cool)(language)/) do
"two" + $1.capitalize + " %s %s %s %s!" % [$2,$3,$4.upcase,$5]
end
p rv
rv =
不能挡住它,所以它不会最终无意间被抓住。
您也可以这样做:
p(
"rubyisacoollanguage".gsub(/(ruby)(is)(a)(cool)(language)/) do
"two" + $1.capitalize + " %s %s %s %s!" % [$2,$3,$4.upcase,$5]
end
)
您要在哪里清楚地弄清谁得到了什么。
答案 2 :(得分:2)
Ruby通常为您提供两种表达同一事物的方法。 block
与p
调用关联,而不与gsub
调用关联。
运算符优先级。