-1

我在 a 的 replace 参数中使用 lambda gsub!。当 lambda 在不同的方法中定义Regexp.last_match$~为空时,与 lambda 在调用时评估表达式的预期行为背道而驰。如果我运行这段代码,我会得到一个错误,但如果我取消注释转录中的第一行,它就会工作。

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')

谁能告诉我我做错了什么,或者这是一个错误?

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

4

2 回答 2

1

正则表达式全局变量(Regexp.last_match只是 $~ 的访问器)根本不是真正的全局变量。从文档last_match

请注意,last_match 对于进行模式匹配的方法的线程和方法范围是本地的。

因此,当您的 lambda 在不同的方法中定义时,方法范围是不同的,因此它访问自己的未设置的私有 Regexp.last_match。最简单的事情可能是Regexp.last_match作为参数传递给你的 lambda

于 2013-01-16T09:12:46.767 回答
0

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

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

这应该可以解决您的问题。

一般来说,$~除非它与正则表达式在同一行,否则我不会使用魔法。它使代码更具可读性。

于 2013-01-16T05:34:02.477 回答