Project

General

Profile

Actions

Bug #21040

closed

String#next! method does not mutate $& variable

Added by radarek (Radosław Bułat) about 21 hours ago. Updated about 19 hours ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin24]
[ruby-core:120696]

Description

String#next! method should mutate string and return mutated version. For some reason, using it on $& does not mutate it but still returns new version.

Steps to reproduce (2 different ways):

"123".gsub(/./){$&.next!}    # returns "234" as expected
"123".gsub(/./){$&.next!;$&} # returns "123" but should be "234"
"123".gsub(/./){_1.next!;_1} # returns "234" as expected



"123"[/./]
puts $&.      # prints 1
puts $&.next! # prints 2
puts $&       # prints 1 but should be 2

Updated by Eregon (Benoit Daloze) about 19 hours ago

  • Status changed from Open to Rejected

$& returns a new String on every usage, so this is fully expected:

$ ruby -e '"a" =~ /a/; p $&.object_id; p $&.object_id' 
60
80

Updated by Hanmac (Hans Mackowiak) about 19 hours ago

These are called virtual variables, a new object is created each time you try to access it

    rb_define_virtual_variable("$~", get_LAST_MATCH_INFO, match_setter);
    rb_define_virtual_variable("$&", last_match_getter, 0);
    rb_define_virtual_variable("$`", prematch_getter, 0);
    rb_define_virtual_variable("$'", postmatch_getter, 0);
    rb_define_virtual_variable("$+", last_paren_match_getter, 0);

in ruby this is the result:


"123".gsub(/.../){
  p [$&, 
     $&.object_id, #=> 30
     $&.object_id  #=> 40
  ]
}
Actions

Also available in: Atom PDF

Like0
Like0Like0