Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the =~ operator only sometimes have side effects?

I've noticed a side effect in Ruby/Oniguruma that is only present in 1 out of 4 seemingly equivalent statements. Why is the variable day defined in 009, but not in 003, 005 or 007?

irb(main):001:0> r = /(?<day>\d\d):(?<mon>\d\d)/
=> /(?<day>\d\d):(?<mon>\d\d)/

irb(main):002:0> r =~ "24:12"
=> 0
irb(main):003:0> day
NameError: undefined local variable or method `day' 

irb(main):004:0> "24:12" =~ r
=> 0
irb(main):005:0> day
NameError: undefined local variable or method `day'


irb(main):006:0> "24:12" =~ /(?<day>\d\d):(?<mon>\d\d)/
=> 0
irb(main):007:0> day
NameError: undefined local variable or method `day'


irb(main):008:0> /(?<day>\d\d):(?<mon>\d\d)/ =~ "24:12"
=> 0
irb(main):009:0> day
=> "24"

nb#1: It's the same regex and the same string in all four cases.

nb#2: I've verified the behavior in MS Windows and Ubuntu Linux.

like image 292
Staffan Nöteberg Avatar asked May 25 '11 12:05

Staffan Nöteberg


2 Answers

When you call "24:12" =~ r you actually call "24:12".=~(r). So, String#=~ just returns the position the match starts, or nil if there is no match.

But when you call /(?<day>\d\d):(?<mon>\d\d)/ =~ "24:12" you actually call Regexp#=~

And as the documentation says

If =~ is used with a regexp literal with named captures, captured strings (or nil) is assigned to local variables named by the capture names.

what about 003:

The assignment is not occur if the regexp is not a literal.

   re = /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
   re =~ "  x = y  "
   p lhs    # undefined local variable
   p rhs    # undefined local variable

and

The assignment is not occur if the regexp is placed at right hand side.
" x = y " =~ /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
p lhs, rhs # undefined local variable

like image 129
Vasiliy Ermolovich Avatar answered Oct 07 '22 14:10

Vasiliy Ermolovich


I believe 003 isn't supported because it's a full blown Regexp object in Rubyland at that point, possibly with overridden methods and such. That makes the scope of assigned locals a lot more complicated.

like image 33
JEG2 Avatar answered Oct 07 '22 13:10

JEG2