-1

a の replace 引数内でラムダを使用していgsub!ます。ラムダが別のメソッドで定義されているRegexp.last_match$~空である場合、呼び出し時に式を評価するラムダの予想される動作に反します。このコードを実行するとエラーが発生しますが、transcribe の最初の行のコメントを外すと動作します。

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 は、パターン マッチを実行したメソッドのスレッドおよびメソッド スコープに対してローカルであることに注意してください。

したがって、ラムダが別のメソッドで定義されている場合、メソッドのスコープが異なるため、設定されていない独自のプライベート Regexp.last_match にアクセスします。Regexp.last_match最も簡単な方法は、おそらくラムダに引数として渡すことです

于 2013-01-16T09:12:46.767 に答える
0

一致をパラメーターとしてブロックに渡すことができます

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

これで問題が解決するはずです。

$~一般に、正規表現と同じ行にない限り、magic like は使用しません。コードが読みやすくなります。

于 2013-01-16T05:34:02.477 に答える