ruge's Regexp.last_match глобальное значение внутри метода - PullRequest
2 голосов
/ 07 сентября 2011

Может кто-нибудь объяснить, почему не работает следующее?Разве $~ не должен быть глобальной переменной, установленной при каждом совпадении с регулярным выражением?

class LocalizedObject < BasicObject
  def initialize(hash)
    @hash=hash
  end

  def method_missing(name, *args)
    @hash[$current_locale || "en"].send(name, *args)
  end
end

proxy = LocalizedObject.new({"en" => "foobarbaz", "pt" => "xpto"})
proxy                                        # => "foobarbaz"

# this won't work as expected

proxy.match(/f.*r/)                          # => #<MatchData "foobar">
Regexp.last_match                            # => nil
$~                                           # => nil

# which would be like this...

"foobarbaz".match(/b.*z/)                    # => #<MatchData "barbaz">
Regexp.last_match                            # => #<MatchData "barbaz">
$~                                           # => #<MatchData "barbaz">

РЕДАКТИРОВАТЬ.хочу добиться .... Я хочу, чтобы LocalizedObject был прозрачным для своих пользователей, поэтому его можно подключить к существующему коду, который я не хочу менять.

Может кто-нибудь придумать, как заставить это работать??

Я использую для этого ruby ​​1.9.2, но я получаю то же самое с 1.8.7 и пользовательским BasicObject, украденным у https://github.com/jeremyevans/sequel/blob/master/lib/sequel/sql.rb

1 Ответ

1 голос
/ 07 сентября 2011

В re.c , строка 3453, упоминается:

Обратите внимание, что last_match является локальным для потока и области действия метода метода, который сделал сопоставление с шаблоном.

Поскольку с вашим прокси-объектом вы выполняете вызов match в method_missing, он будет виден именно там, как можно увидеть, если вы измените его на

def method_missing(name, *args)
  res = @object.send(name, *args)
  Kernel.p $~
  res
end 

UPDATE:

Довольно некрасиво, но, может быть, что-то вроде этого - вариант?

#!/usr/local/bin/ruby19

def set_current_locale(l)
  $current_locale = l
  ObjectSpace.each_object { | obj |
    obj.adjust_locale if obj.respond_to? :adjust_locale
  }
end

class LocalizedObject < String
  def initialize(hash)
    super(hash[$current_locale || "en"])
    @hash = hash
  end

  def adjust_locale
    self[0..-1] = @hash[$current_locale || "en"] if @hash
  end
end

proxy = LocalizedObject.new({"en" => "foobarbaz", "pt" => "xpto"})

proxy.match(/f.*r/)                          # => #<MatchData "foobar">
Regexp.last_match                            # => #<MatchData "foobar">
$~                                           # => #<MatchData "foobar">

set_current_locale('pt')

proxy.match(/x.*o/)                          # => #<MatchData "xpto">
Regexp.last_match                            # => #<MatchData "xpto">
$~                                           # => #<MatchData "xpto">
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...