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

**URL:** <https://www.ruby-forum.com/t/how-to-make-objects-that-can-set-1-when-obj-is-cal/101830>\
**Category:** Ruby\
**Created:** [August 8, 2006, 7:52am UTC](https://www.ruby-forum.com/t/how-to-make-objects-that-can-set-1-when-obj-is-cal/101830 "2006-08-08T07:52:58Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![fmwr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/9de053/32.png) [@fmwr](https://www.ruby-forum.com/u/fmwr)\
**Post date:** [August 8, 2006, 7:52am UTC](https://www.ruby-forum.com/t/how-to-make-objects-that-can-set-1-when-obj-is-cal/101830/1 "2006-08-08T07:52:58Z")

</div>

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 ?

---

<div class="post-metadata">

**Author:** ![fmwr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/9de053/32.png) [@fmwr](https://www.ruby-forum.com/u/fmwr)\
**Post date:** [August 8, 2006, 10:26am UTC](https://www.ruby-forum.com/t/how-to-make-objects-that-can-set-1-when-obj-is-cal/101830/2 "2006-08-08T10:26:08Z")

</div>

Tomasz W. wrote:

> 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
```

---

<div class="post-metadata">

**Author:** ![fmwr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/9de053/32.png) [@fmwr](https://www.ruby-forum.com/u/fmwr)\
**Post date:** [August 9, 2006, 8:32pm UTC](https://www.ruby-forum.com/t/how-to-make-objects-that-can-set-1-when-obj-is-cal/101830/3 "2006-08-09T20:32:19Z")

</div>

On 8/8/06, Mauricio F. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > And it works for non-capturing regexps,
> 
> [ruby-talk:202600]

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

---

<div class="post-metadata">

**Author:** ![fmwr](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/9de053/32.png) [@fmwr](https://www.ruby-forum.com/u/fmwr)\
**Post date:** [August 8, 2006, 10:41am UTC](https://www.ruby-forum.com/t/how-to-make-objects-that-can-set-1-when-obj-is-cal/101830/4 "2006-08-08T10:41:09Z")

</div>

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

> 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]
