On Wed, Jul 19, 2006 at 07:13:10AM +0900, Brendan Baldwin wrote:
> Consider the following Regexp/MatchData extension, which pops a copy of 
> the original Regexp into the MatchData object resulting from 
> Regexp#match.  Forget for a minute *why* anyone might want to do this:
> 
>     class Regexp
>       alias_method :original_match, :match
>       def match(str)
>         m=self.original_match(str)
>         m.regexp=self unless m.nil?
>         m
>       end
>     end
>     class MatchData
>       attr_accessor :regexp
>     end
> 
> Because of the magical nature of the $~ global variable and its 
> derivatives $&,$+,$`,$',$1-9, we wind up losing it from scope with this 
> extension to the Regexp class:
> 
>   /myregexp/.match("test my regexp")
>   $~ # <= nil
> 
> Is anyone out there aware of any way to set $~ in the "caller's" binding 
> from within Regexp#match *without* requiring a manual call_stack to be 
> implemented via set_trace_func?

hmm the only general way I'm aware of does use Binding.of_caller (and
therefore set_trace_func), see for instance [150292]. However, if your method
took a block, it'd be easily doable.

Silly example:

class Regexp
  alias_method :_original_match, :match
  def match(*str, &block)
    if block_given?
      md = _original_match(yield)
      eval("lambda{|x| $~ = x}", block).call($~)   
    else
      md = _original_match(*str)
    end
    md.regexp = self if md
    md
  end
end

class MatchData
  attr_accessor :regexp
end

/myregexp/.match{"test myregexp"} 
# note the syntax change; you might find this unacceptable :-|
$~                                 # => #<MatchData:0xa7d26fd4>
$~.regexp                          # => /myregexp/
$~.pre_match                       # => "test "


Sorry if this doesn't really help.

-- 
Mauricio Fernandez  -   http://eigenclass.org   -  singular Ruby