Bog*_*iev 8 ruby scope pseudo-globals
给出以下两段代码:
def hello(z)
"hello".gsub(/(o)/, &z)
end
z = proc {|m| p $1}
hello(z)
# prints: nil
Run Code Online (Sandbox Code Playgroud)
def hello
z = proc {|m| p $1}
"hello".gsub(/(o)/, &z)
end
hello
# prints: "o"
Run Code Online (Sandbox Code Playgroud)
为什么这两段代码的输出不同?有没有一种方法,以块传递到gsub从方法定义之外,这样的变量$1,$2将被以同样的方式,就好像块的方法定义中给出的评价?
\n\n为什么输出不同?
\n
ruby 中的过程有词法作用域。这意味着当它找到未定义的变量时,它会在定义过程的上下文中解析,而不是调用。这解释了您的代码的行为。
\n您可以看到该块是在正则表达式之前定义的,这可能会导致混乱。该问题涉及一个神奇的 ruby 变量,它的工作方式与其他变量完全不同。引用@J\xc3\xb6rgWMittag
\n\n\n实际上,这相当简单: $SAFE 的行为与您对全局变量的期望不同的原因是因为它不是全局变量。这是一个神奇的独角兽。
\nRuby 中有相当多的神奇独角兽,不幸的是,它们没有很好的文档记录(事实上,根本没有文档记录),因为替代 Ruby 实现的开发人员很难发现。这些东西的行为都不同并且(看起来)不一致,而且它们几乎唯一的两个共同点是它们看起来像全局变量,但行为却不像它们。
\n有些具有本地范围。有些具有线程本地范围。有些会神奇地发生变化,而无需任何人分配给它们。有些对于解释器来说具有神奇的意义,可以改变语言的行为方式。有些还附加了其他奇怪的语义。
\n
如果您真的想确切地了解$1和$2变量如何工作,我假设您会找到的唯一“文档”是rubyspec,这是由 Rubinus 人员艰难完成的 ruby 规范。祝你黑客攻击愉快,但要做好承受痛苦的准备。
\n\n有没有办法以正确的方式将 $1、$2 变量设置从另一个上下文传递给 gsub 块?
\n
您可以通过以下修改实现您想要的效果(但我打赌您已经知道了)
\nrequire \'pp\'\ndef hello(z)\n #z = proc {|m| pp $1}\n "hello".gsub(/(o)/, &z)\nend\nz = proc {|m| pp m}\nhello(z)\nRun Code Online (Sandbox Code Playgroud)\n我不知道如何动态更改过程的范围。但你真的想这样做吗?
\n| 归档时间: |
|
| 查看次数: |
1004 次 |
| 最近记录: |