在Ruby中,Regexp#~一元运算符如何取别名?
In Ruby, how can the Regexp#~ unary operator be aliased?
利用 Ruby 在其基本功能中提供的自由,我发现为该语言中使用的大多数运算符取别名相当容易,但 the Regexp#~ unary prefix operator 比较棘手。
第一个天真的方法是在 Regexp class 本身中给它起别名
class Regexp
alias hit ~@ # remember that @ stands for "prefix version"
# Note that a simple `alias_method :hit, :~@` will give the same result
end
正如在下面的一些回答中指出的那样,这种方法 是 以某种方式与点符号调用形式一起工作,例如 /needle/.hit
。然而,尝试执行 hit /needle/
会引发 undefined method
hit' for main:Object (NoMethodError)`
所以另一种天真的方法是在 Object
中定义这个方法,比如
class Object
def ~@(pattern)
pattern =~ $_
end
end
然而,这是行不通的,因为 $_
全局变量实际上是本地绑定的,不会保留它在调用上下文中的值,即 $_
总是nil
在前面的片段中。
所以问题是,是否可以使用表达式 hit /needle/
来恢复与 ~ /needle/
相同的结果?
对我来说效果很好:
class Regexp
alias_method :hit, :~ # both of them work
# alias hit ~ # both of them work
end
$_ = "input data"
/at/.hit #=> 7
~/at/ #=> 7
/at/.hit #=> 7
~/at/ #=> 7
因此,由于已完成的问题现在抑制了它,主要障碍是 $_
的范围狭窄。这就是 trace_var
可以提供帮助的地方:
trace_var :$_, proc { |nub|
$last_explicitly_read_line = nub
#puts "$_ is now '#{nub}'"
}
def reach(pattern)
$last_explicitly_read_line =~ pattern
end
def first
$_ = "It’s needless to despair."
end
def second
first
p reach /needle/
$_ = 'What a needlework!'
p reach /needle/
end
p reach /needle/
second
p reach /needle/
$_ = nil
p reach /needle/
所以基本的想法是在每次更改时将 $_
的值存储在另一个变量中,该变量将在其他后续调用上下文中访问。这里它是用另一个全局变量实现的(不是本地绑定的,当然不像 $_
),但是用其他实现可以获得相同的结果,比如在 [=15= 上定义一个 class 变量].
人们也可以尝试使用类似 binding_of_caller or binding_ninja 的方法,但我自己的方法失败了,当然它还带有其他依赖项,这些依赖项有其自身的局限性。
利用 Ruby 在其基本功能中提供的自由,我发现为该语言中使用的大多数运算符取别名相当容易,但 the Regexp#~ unary prefix operator 比较棘手。
第一个天真的方法是在 Regexp class 本身中给它起别名
class Regexp
alias hit ~@ # remember that @ stands for "prefix version"
# Note that a simple `alias_method :hit, :~@` will give the same result
end
正如在下面的一些回答中指出的那样,这种方法 是 以某种方式与点符号调用形式一起工作,例如 /needle/.hit
。然而,尝试执行 hit /needle/
会引发 undefined method
hit' for main:Object (NoMethodError)`
所以另一种天真的方法是在 Object
中定义这个方法,比如
class Object
def ~@(pattern)
pattern =~ $_
end
end
然而,这是行不通的,因为 $_
全局变量实际上是本地绑定的,不会保留它在调用上下文中的值,即 $_
总是nil
在前面的片段中。
所以问题是,是否可以使用表达式 hit /needle/
来恢复与 ~ /needle/
相同的结果?
对我来说效果很好:
class Regexp
alias_method :hit, :~ # both of them work
# alias hit ~ # both of them work
end
$_ = "input data"
/at/.hit #=> 7
~/at/ #=> 7
/at/.hit #=> 7
~/at/ #=> 7
因此,由于已完成的问题现在抑制了它,主要障碍是 $_
的范围狭窄。这就是 trace_var
可以提供帮助的地方:
trace_var :$_, proc { |nub|
$last_explicitly_read_line = nub
#puts "$_ is now '#{nub}'"
}
def reach(pattern)
$last_explicitly_read_line =~ pattern
end
def first
$_ = "It’s needless to despair."
end
def second
first
p reach /needle/
$_ = 'What a needlework!'
p reach /needle/
end
p reach /needle/
second
p reach /needle/
$_ = nil
p reach /needle/
所以基本的想法是在每次更改时将 $_
的值存储在另一个变量中,该变量将在其他后续调用上下文中访问。这里它是用另一个全局变量实现的(不是本地绑定的,当然不像 $_
),但是用其他实现可以获得相同的结果,比如在 [=15= 上定义一个 class 变量].
人们也可以尝试使用类似 binding_of_caller or binding_ninja 的方法,但我自己的方法失败了,当然它还带有其他依赖项,这些依赖项有其自身的局限性。