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?
I played around with this for MetaRuby and couldn't find a way to implement it. I believe it is impossible outside of set_trace_func/evil.rb level hackery.
···
On Jul 18, 2006, at 3:13 PM, Brendan Baldwin wrote:
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?
--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant
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.
···
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?
The block implentation is pretty cool -- My problem is I was trying to
modify Regexp#match for use with a production application at my current
employer, which also uses the REXML library, that unfortunately uses $~
vars all over and doesn't use blocks to get at them, so it breaks.
And I'm constrained in not using set_trace_func here, so that's
unfortunatlely out of the picture too.
*Sigh*
Darn little esoteric PERLy $~ !! Oh well. Spent more time than I
should have on this already... Perhaps Ruby 1.9 or 2.0 will give us
caller bindings for free some day.
--Brendan
Mauricio Fernandez wrote:
···
On Wed, Jul 19, 2006 at 07:13:10AM +0900, Brendan Baldwin wrote:
end
$~ # <= 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 "
The block implentation is pretty cool -- My problem is I was trying to
modify Regexp#match for use with a production application at my current
employer, which also uses the REXML library, that unfortunately uses $~
vars all over and doesn't use blocks to get at them, so it breaks.
And I'm constrained in not using set_trace_func here, so that's
unfortunatlely out of the picture too.