【发布时间】:2015-05-28 17:09:42
【问题描述】:
我正在尝试为使用 Ruby 的特殊 $& (returns last regex match) 的方法命名。我可以手动执行此操作,并且有效:
original = String.instance_method(:sub)
String.send(:define_method, :sub) do |*args, &block|
puts "called"
original.bind(self).call(*args, &block)
end
"foo".sub(/f/) { $&.upcase }
called
# => "Foo"
但是,如果我尝试编写一个为我执行此操作的方法,它会失败:
def programatic_alias(klass, method_name)
original = klass.instance_method(method_name)
klass.send(:define_method, method_name) do |*args, &block|
puts "called"
original.bind(self).call(*args, &block)
end
end
programatic_alias(String, :sub)
"foo".sub(/f/) { $&.upcase }
called
NoMethodError: undefined method `upcase' for nil:NilClass
called
called
called
from (irb):19:in `block in irb_binding'
看起来全局状态正受到programatic_alias 方法范围的影响,但我不确定是否是这样。问题是这样的:我如何以编程方式为String#sub 别名,以便它仍然可以与Ruby 的特殊全局变量一起使用?
【问题讨论】:
-
您使用的是什么版本的 ruby?对我来说,2.2.1 你的例子是有效的。
-
我使用的是 Ruby 2.2.2。您需要确保在不同的脚本/irb 会话中运行示例,否则您可能正在使用之前定义的方法别名。我在本地机器上尝试了 2.2.1,能够重现该问题。
-
为什么要使用
$&全局变量? -
@hakcho ¯_(ツ)_/¯ 但它在野外还活着github.com/rails/rails/blob/master/activesupport/lib/…
-
我看到了一个更简单的替代您的问题的方法,这就是我问的原因。此外,您可以read 使用它们是不被接受的好习惯。
标签: ruby global-variables metaprogramming