Почему оператор = ~ только иногда имеет побочные эффекты?
Я заметил побочный эффект в Ruby/Oniguruma, который присутствует только в 1 из 4, казалось бы, эквивалентных утверждений. Почему переменная day
определена в 009
, но не в 003
, 005
или 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: Это одно и то же регулярное выражение и одна и та же строка во всех четырех случаях.
nb # 2: Я проверил поведение в MS Windows и Ubuntu Linux.
Ответы
Ответ 1
Когда вы вызываете "24:12" =~ r
, вы на самом деле вызываете "24:12".=~(r)
. Итак, String # = ~ просто возвращает позицию, с которой начинается совпадение, или nil, если нет совпадения.
Но когда вы вызываете /(?<day>\d\d):(?<mon>\d\d)/ =~ "24:12"
, вы на самом деле вызываете Regexp # = ~
И как говорится в документации
If = ~ используется с литералом regexp с именованными захватами, захваченные строки (или nil) присваивается локальному переменные, названные именами захвата.
как насчет 003
:
Назначение не возникает, если regexp не является литералом.
re = /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
re =~ " x = y "
p lhs # undefined local variable
p rhs # undefined local variable
и
Назначение не возникает, если regexp помещается с правой стороны.
"x = y" = ~ /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
п lhs, rhs # undefined Локальная переменная
Ответ 2
Я считаю, что 003 не поддерживается, потому что он полностью переработанный объект Regexp в Rubyland в этот момент, возможно, с переопределенными методами и т.д. Это делает объем назначенных локальных жителей намного сложнее.