How to make objects that can set $1 when obj =~ /(.)/ is called?

Something like that would be a reasonable thing to do:

class Foo
  def initialize(t)
    @text = t
  end
  def =~(x)
    @text =~ x
  end
end

And it works for non-capturing regexps,
but when we want to capture something
$1 etc. are bound only within the =~ method,
and when the method returns they are
restored to their previous values.

Foo.new("Hello") =~ /(e)/ # => 1
$1 # => nil

Is it possible to somehow get =~ like that work,
even if it takes heavy metaprogramming hackery ?

···

--
Tomasz Wegrzanowski [ http://t-a-w.blogspot.com/ ]

Tomasz Wegrzanowski wrote:

Something like that would be a reasonable thing to do:

class Foo
def initialize(t)
   @text = t
end
def =~(x)
   @text =~ x
end
end

And it works for non-capturing regexps,
but when we want to capture something
$1 etc. are bound only within the =~ method,
and when the method returns they are
restored to their previous values.

Foo.new("Hello") =~ /(e)/ # => 1
$1 # => nil

Is it possible to somehow get =~ like that work,
even if it takes heavy metaprogramming hackery ?

The simplest solution might be to use #match:

class Foo
  def initialize(t)
    @text = t
  end
  def =~(x)
    x.match @text
  end
end

>> md = Foo.new("Hello") =~ /(e)l/
=> #<MatchData:0x3a40c0>
>> md.to_a
=> ["el", "e"]

You can do more of course, like storing MatchData along with your Foo instance etc. What problem are you trying to solve?

Kind regards

  robert

[ruby-talk:202600]

···

On Tue, Aug 08, 2006 at 02:51:37PM +0900, Tomasz Wegrzanowski wrote:

class Foo
def initialize(t)
   @text = t
end
def =~(x)
   @text =~ x
end
end

And it works for non-capturing regexps,
but when we want to capture something
$1 etc. are bound only within the =~ method,
and when the method returns they are
restored to their previous values.

Foo.new("Hello") =~ /(e)/ # => 1
$1 # => nil

Is it possible to somehow get =~ like that work,
even if it takes heavy metaprogramming hackery ?

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

I finally got a working solution, using Binding.of_caller.
Not very elegant, but it works:

class Foo
    def =~(pattern)
        rv = (@text =~ pattern)
        Binding.of_caller {|binding|
            set_rx_vars = eval("lambda{|md| $~ = md}", binding)
            set_rx_vars.call($~)
            rv
        }
    end
end

···

On 8/8/06, Mauricio Fernandez <mfp@acm.org> wrote:

On Tue, Aug 08, 2006 at 02:51:37PM +0900, Tomasz Wegrzanowski wrote:
> class Foo
> def initialize(t)
> @text = t
> end
> def =~(x)
> @text =~ x
> end
> end
>
> And it works for non-capturing regexps,
> but when we want to capture something
> $1 etc. are bound only within the =~ method,
> and when the method returns they are
> restored to their previous values.
>
> Foo.new("Hello") =~ /(e)/ # => 1
> $1 # => nil
>
> Is it possible to somehow get =~ like that work,
> even if it takes heavy metaprogramming hackery ?

[ruby-talk:202600]

--
Tomasz Wegrzanowski [ http://t-a-w.blogspot.com/ ]