2013-01-16 95 views
-1

我在gsub!的替换参数内使用lambda。当以不同的方法定义lambda时,Regexp.last_match$~为空,违背了lambda在调用时评估表达式的预期行为。如果我运行这个代码,我会得到一个错误,但是如果我在转录的第一行取消注释,它就会起作用。当在另一种方法中定义lambda时,`lambda中的Regexp.last_match`调用为`nil`

class Test 
    def initialize 
    @@replace = lambda { "#{callback('*', Regexp.last_match)}" } 
    end 

    def transcribe(s) 
    #@@replace = lambda { "#{callback('*', Regexp.last_match)}" } 
    s.gsub!(/(?<l>.?)[aeiou](?<r>.?)/) do 
     $~[:l] + (@@replace).call + $~[:r] 
    end 
    s 
    end 

    def callback(replace, match) 
    raise "Error: Match is empty" if match.nil? 
    return replace.upcase 
    end 
end 

t = Test.new 
puts t.transcribe('example') 

有人可以告诉我,如果我做错了什么,或者它是一个错误?

我用Google搜索了它:ruby Regexp.last_match lambda,并且在不同的情况下,似乎有一个$1的错误,但我不明白它是否与此相关。

回答

0

可以匹配作为参数传递给块

s.gsub!(/(?<l>.?)[aeiou](?<r>.?)/) do |match| 
    $~[:l] + (@@replace).call(match) + $~[:r] 
end 

这应该解决您的问题。

一般来说,我不会使用类似$~的魔术,除非它与正则表达式位于同一行。它使代码更具可读性。

1

正则表达式全局变量(Regexp.last_match只是$〜的一个访问器)根本就不是全局的。从docslast_match

注意,last_match是局部的,做了 模式匹配方法的线程 和方法的范围。

因此,当你的lambda被定义在一个不同的方法中时,方法范围是不同的,所以它访问它自己的专用Regexp.last_match,它没有设置。最简单的事情可能是通过Regexp.last_match作为你的lambda的参数

相关问题