Bug #11808
openDifferent behavior between Enumerable#grep and Array#grep
Description
Regex special global variables are available within the block for Array#grep
, but are nil within the block for Enumerable#grep
.
Here is an example that explains it better:
class Test
include Enumerable
def each
return enum_for(:each) unless block_given?
yield "Hello"
yield "World"
end
end
enum = Test.new
array = ["Hello", "World"]
enum.grep(/^(.)/) {$1} # => [nil, nil]
array.grep(/^(.)/) {$1} # => ["H", "W"]
Tested on 2.0.0, 2.1.5, & 2.2.2
Updated by jeremyevans0 (Jeremy Evans) almost 4 years ago
Array#grep
is actually Enumerable#grep
:
Array.instance_method(:grep).owner
=> Enumerable
If I had to guess, the cause of the difference is that Array#each
is implemented in C, and Test#each
is implemented in Ruby, and this affects Regexp special variable scope. You see similar behavior as Array in other classes that implement #each
in C, such as Range or File.
The documentation for the special global variables states: These global variables are thread-local and method-local variables.
This indicates to me that the bug is that the variables are accessible inside the Array#each
block, since that block executes inside the current method, it's not local to the Array#each
method. However, I would assume removing the current behavior would break too much existing code.
Updated by nobu (Nobuyoshi Nakada) almost 4 years ago
- Tracker changed from Bug to Feature
- Description updated (diff)
- ruby -v deleted (
2.2.2) - Backport deleted (
2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN)
There is no API for it now.
Updated by nobu (Nobuyoshi Nakada) almost 4 years ago
- Subject changed from DIfferent behavior between Enumerable#grep and Array#grep to Different behavior between Enumerable#grep and Array#grep
Updated by matz (Yukihiro Matsumoto) almost 4 years ago
- Tracker changed from Feature to Bug
- Backport set to 2.5: UNKNOWN, 2.6: UNKNOWN
It is a bug. It has been hidden for 10+ years and seems to be very difficult to fix.
It should be fixed in the long run.
Matz.
Updated by ko1 (Koichi Sasada) almost 4 years ago
- Assignee set to ko1 (Koichi Sasada)
Updated by ko1 (Koichi Sasada) over 2 years ago
Sorry we need more time to consider.