为什么输出不一样?
ruby 中的 proc 具有词法范围。这意味着当它找到一个未定义的变量时,它会在 proc 被定义的上下文中被解析,而不是被调用。这解释了您的代码的行为。
您可以看到块是在正则表达式之前定义的,这可能会导致混淆。这个问题涉及一个神奇的 ruby 变量,它的工作方式与其他变量完全不同。引用@JörgWMittag
真的很简单:$SAFE 的行为不像您对全局变量的期望那样的原因是因为它不是全局变量。这是一个神奇的独角兽东西amajiggy。
Ruby 中有很多这样神奇的独角兽 thingamajiggies,不幸的是,它们的文档记录不是很好(实际上根本没有文档记录),因为替代 Ruby 实现的开发人员发现了困难的方式。这些 thingamajiggies 的行为都不同且(似乎)不一致,它们唯一的两个共同点是它们看起来像全局变量,但行为却不像它们。
有些有本地范围。有些具有线程本地范围。有些神奇地改变了,没有任何人分配给他们。有些对解释器具有神奇的意义,并改变了语言的行为方式。有些还附加了其他奇怪的语义。
如果您真的想知道$1
and$2
变量是如何工作的,我假设您会找到的唯一“文档”是rubyspec ,这是由 Rubinus 人艰难完成的 ruby 规范。有一个很好的黑客攻击,但要为痛苦做好准备。
有没有办法通过正确的方式设置 $1, $2 变量从另一个上下文将块传递给 gsub?
您可以通过以下修改实现您想要的(但我敢打赌您已经知道了)
require 'pp'
def hello(z)
#z = proc {|m| pp $1}
"hello".gsub(/(o)/, &z)
end
z = proc {|m| pp m}
hello(z)
我不知道有一种方法可以即时更改 proc 的范围。但你真的想这样做吗?