# Match data variables

**URL:** <https://www.ruby-forum.com/t/match-data-variables/169952>\
**Category:** Ruby\
**Created:** [June 10, 2009, 5:04pm UTC](https://www.ruby-forum.com/t/match-data-variables/169952 "2009-06-10T17:04:45Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![larsch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/ad7895/32.png) [@larsch](https://www.ruby-forum.com/u/larsch)\
**Post date:** [June 10, 2009, 5:04pm UTC](https://www.ruby-forum.com/t/match-data-variables/169952/1 "2009-06-10T17:04:45Z")

</div>

I understand that $~ and its friends ($&, $1, …) are method local,  
but:

Can a custom method mimic the behaviour of String#match, String#=~ etc  
and set the match data for the caller?

def expect(pattern)  
gets =~ pattern or fail  
end

expect /(\d+)/

p $1 #=\> nil  
p $~ #=\> nil ☹

I would like $~ to contain the match data here.

---

<div class="post-metadata">

**Author:** ![larsch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/ad7895/32.png) [@larsch](https://www.ruby-forum.com/u/larsch)\
**Post date:** [June 10, 2009, 6:15pm UTC](https://www.ruby-forum.com/t/match-data-variables/169952/2 "2009-06-10T18:15:49Z")

</div>

Lars C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> p $1 #=\> nil  
> p $~ #=\> nil ☹
> 
> I would like $~ to contain the match data here.

Regexp.last\_match is a MatchData object and you can do whatever you like  
with it. For example:

def expect(str, pattern)  
str =~ pattern  
Regexp.last\_match  
end  
res = expect(“howdy”, /h/)  
p res.begin(0)

You could even set some _other_ global to Regexp.last\_match, if you’re  
in a “use globals” mood…

m.

---

<div class="post-metadata">

**Author:** ![larsch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/ad7895/32.png) [@larsch](https://www.ruby-forum.com/u/larsch)\
**Post date:** [June 10, 2009, 8:45pm UTC](https://www.ruby-forum.com/t/match-data-variables/169952/3 "2009-06-10T20:45:24Z")

</div>

On Wed, Jun 10, 2009 at 10:03 AM, Lars  
Christensen[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I understand that $~ and its friends ($&, $1, …) are method local, but:
> 
> Can a custom method mimic the behaviour of String#match, String#=~ etc  
> and set the match data for the caller?

No. There is no way (without a supergross hack like using  
set\_trace\_func or something).

This is one of my strongest arguments against those variables and  
methods that manipulate them, since they have this extra “magic”  
behavior that you can’t mimic in Ruby code (without  
implementation-specific hacks). For this reason no methods that  
access/modify $~ or $\_ should ever be wrapped or aliased, and we even  
warn against aliasing in JRuby since we use the presence of those  
methods to make some optimization decisions.

I wish $~ and $\_ were not in the language.

- Charlie

---

<div class="post-metadata">

**Author:** ![larsch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/ad7895/32.png) [@larsch](https://www.ruby-forum.com/u/larsch)\
**Post date:** [June 10, 2009, 11:11pm UTC](https://www.ruby-forum.com/t/match-data-variables/169952/4 "2009-06-10T23:11:32Z")

</div>

On 10.06.2009 17:03, Lars C. wrote:

> p $1 #=\> nil  
> p $~ #=\> nil ☹
> 
> I would like $~ to contain the match data here.

What stops you from

a) returning the MatchData instance from expect(), for example by using  
#match  
b) yielding the match data from expect to a block

? Why do you believe you need to somehow inject something into the  
caller’s environment?

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![larsch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/ad7895/32.png) [@larsch](https://www.ruby-forum.com/u/larsch)\
**Post date:** [June 11, 2009, 3:35pm UTC](https://www.ruby-forum.com/t/match-data-variables/169952/5 "2009-06-11T15:35:50Z")

</div>

Robert K. wrote:

> What stops you from

[snip]

> b) yielding the match data from expect to a block

Can the yielded block see the $1, $2, $3 vars?

(Sorry for not checking this out myself, my Ruby system is broken. BTW,  
I’m not the original poster.)

---

<div class="post-metadata">

**Author:** ![larsch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/ad7895/32.png) [@larsch](https://www.ruby-forum.com/u/larsch)\
**Post date:** [June 11, 2009, 3:47pm UTC](https://www.ruby-forum.com/t/match-data-variables/169952/6 "2009-06-11T15:47:50Z")

</div>

2009/6/11 Albert S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Robert K. wrote:
> 
> > What stops you from
> 
> [snip]
> 
> > b) yielding the match data from expect to a block
> 
> Can the yielded block see the $1, $2, $3 vars?

No but it would be easy to provide a MatchData instance or whatever  
suits the use case best via block parameters.

Cheers

robert
