Bug #11304


[PATCH] Kernel.global_variables should observe $~.

Added by 0x0dea (D.E. Akers) over 6 years ago. Updated over 1 year ago.

Target version:


The added complexity does impact performance, but the difference is negligible, and the method should return what it says it does.


global_variables_captures.patch (1.85 KB) global_variables_captures.patch 0x0dea (D.E. Akers), 06/24/2015 11:08 AM

Updated by jeremyevans0 (Jeremy Evans) over 2 years ago

All of the other similar regexp variables ($& $' $+ $~ $(backquote)) are listed by global_variables, so it would make sense for $1 and similar to appear, or alternatively for the other 5 regexp globals not to appear if there is no match. If there is no backref, the other 5 regexp globals still appear. If there is a backref, and it has no captures, it doesn't make sense for $+ to be included and $1 not to be included.

I'm not sure whether $1 through $9 should be present for consistency, even the last match did not have that number of captures. I think that would be more consistent to include all of them if we are including $+ in the case of no matches. However, that would make global_variables less consistent with defined?.

Related to this, defined? is a little strange for the regexp globals:

puts %w[$~ $& $` $' $+ $1 $2].map{|s| "#{s}: #{eval("defined?(#{s})").inspect}"}
# $~: "global-variable"
# $&: nil
# $`: nil
# $': nil
# $+: nil
# $1: nil
# $2: nil

/(.)/ =~ "a"
puts %w[$~ $& $` $' $+ $1 $2].map{|s| "#{s}: #{eval("defined?(#{s})").inspect}"}
# $~: "global-variable"
# $&: "global-variable"
# $`: "global-variable"
# $': "global-variable"
# $+: "global-variable"
# $1: "global-variable"
# $2: nil

I would assume that defined?($~) should be nil if the others are nil. Alternatively, it would make sense for defined? to always return global-variable for $& $' $~ $(backquote). $! is similar to the regexp globals in terms of scoping, and it returns global-variable even if not set.

I checked and defined?($+) is nil if the backref has no captures. I don't think we can change the behavior of defined?($+) or defined?($1) without significantly breaking backwards compatibility.

Also kind of weird is that defined? treats aliases of these global variables differently than it treats the variables themselves:

defined?($&) # nil
alias $MATCH $&
defined?($&) # nil
defined?($MATCH) # "global-variable"

I would think we would want defined? to treat global variable aliases the same as the global variables they alias.

Updated by Eregon (Benoit Daloze) over 2 years ago

$1 - $N (there can be more than 9 of them) are treated specially by the parser.
In fact, the only way they can work is special treatment by the parser, because there is potentially an infinite number of them.

And that's probably why aliasing them is also forbidden:

> alias $ONE $1
SyntaxError: (eval):2: can't make alias for the number variables

The other Regexp global variables, except $~, can be considered "computed" global variables, i.e., they don't need to be actually set and can just be derived from $~.
Finally, all Regexp global variables are not actually global, they are thread-local and frame-local.

So I think this is mostly a documentation bug, $1-$N are special and are actually never defined/registered as global variables (because there is an unbounded number of them), while the rest are.
I think it make sense for Kernel#global_variables to return all global variables that were actually defined/registered, but not $1-$N since they never are defined/registered.

Updated by ko1 (Koichi Sasada) about 2 years ago

  • Assignee set to matz (Yukihiro Matsumoto)

Updated by matz (Yukihiro Matsumoto) over 1 year ago

The current behavior should be as it is. If there can be a clearer description in the document, PR welcome.


Actions #5

Updated by jeremyevans0 (Jeremy Evans) over 1 year ago

  • Status changed from Open to Closed

Also available in: Atom PDF