[Q] $1, $2, ... in block argument of grep()

Array#grep(/pat/){...} allows me to get $1, $2, ... in block argument,
but Enumerable#grep(/pat/){...} doesn't.

Example code:

    01: class ArrayWrapper
    02: include Enumerable
    03: def initialize(arr)
    04: @arr = arr
    05: end
    06: def each(&block)
    07: @arr.each(&block)
    08: end
    09: #def grep(pat, &block)
    10: # @arr.grep(pat, &block)
    11: #end
    12: end
    13:
    14: arr = ["A1.png", "B1.jpg", "C1.gif"]
    15: p arr.grep(/(\.png)$/) { $1 } #=> [".png"]
    16:
    17: obj = ArrayWrapper.new(arr)
    18: p obj.grep(/(\.png)$/) { $1 } #=> [nil]

At line 15, $1 in block argument holds matched value.
(This behavior is what I expected.)
But at line 18, $1 is nil.

What is wrong at line 18?

···

--
kwatch

Array#grep(/pat/){...} allows me to get $1, $2, ... in block argument,
but Enumerable#grep(/pat/){...} doesn't.

Example code:

    01: class ArrayWrapper
    02: include Enumerable
    03: def initialize(arr)
    04: @arr = arr
    05: end
    06: def each(&block)
    07: @arr.each(&block)
    08: end
    09: #def grep(pat, &block)
    10: # @arr.grep(pat, &block)
    11: #end
    12: end
    13:
    14: arr = ["A1.png", "B1.jpg", "C1.gif"]
    15: p arr.grep(/(\.png)$/) { $1 } #=> [".png"]
    16:
    17: obj = ArrayWrapper.new(arr)
    18: p obj.grep(/(\.png)$/) { $1 } #=> [nil]

Please don't put line numbers in next time. It makes it more difficult to run your code.

At line 15, $1 in block argument holds matched value.
(This behavior is what I expected.)
But at line 18, $1 is nil.

What is wrong at line 18?

Nothing is wrong with line 18. If you use `.methad(:grep)` on each object, you can see that they're the same implementation of grep.

What is wrong is how $1 and friends work. They clear out when crossing a call boundary, so your each, wrapping @arr.each, causes the values to get wiped out. A _horrible_ workaround... and I need to stress HORRIBLE is:

class ArrayWrapper
  include Enumerable
  def initialize(arr)
    @arr = arr
    meta = (class << self; self; end)
    meta.send :define_method, :each, &@arr.method(:each)
  end
end

arr = ["A1.png", "B1.jpg", "C1.gif"]
p arr.grep(/(\.png)$/) { $1 } #=> [".png"]

obj = ArrayWrapper.new(arr)
p obj.grep(/(\.png)$/) { $1 } #=> [".png"]

Don't use that code. Really.

···

On Aug 14, 2015, at 08:12, Makoto Kuwata <kwatch@gmail.com> wrote: