Forum: Ruby lambda with $1 fails as gsub block

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A246f7c0ce5f2909483d358bd9e83e4e?d=identicon&s=25 Mike Gold (mikegold)
on 2008-12-11 00:25
I came across this problem:

  def meth(replace)
    ">x".gsub(%r!(\W)x!, &replace)
  end

  replace = lambda { |match|
    puts "$1 is #{$1.inspect}"
  }

  ">x".gsub(%r!(\W)x!, &replace)  # => $1 is ">"

  "" =~ %r!!  # reset $1

  meth(replace)  # => $1 is nil

Apparently $1 is bound in a peculiar way:

  http://groups.google.com/group/comp.lang.ruby/brow...

Matz suggested that the MatchData could have been passed to the block
for convenience, however it looks more like a necessity, as I don't see
a solution short of rewriting gsub.

This suggests that for 1.9, MatchData should be passed as an optional
second argument to the block.  Yes?
Cf7cd97cdc8ed7d4ae92965b24f0dfad?d=identicon&s=25 Stefan Rusterholz (apeiros)
on 2008-12-11 09:51
Mike Gold wrote:
>
> I came across this problem:
>
>   def meth(replace)
>     ">x".gsub(%r!(\W)x!, &replace)
>   end
>
>   replace = lambda { |match|
>     puts "$1 is #{$1.inspect}"
>   }
>
>   ">x".gsub(%r!(\W)x!, &replace)  # => $1 is ">"
>
>   "" =~ %r!!  # reset $1
>
>   meth(replace)  # => $1 is nil
>
> Apparently $1 is bound in a peculiar way:

Interesting issue. A work-around:
module MDGsub
  def md_gsub(pattern)
    gsub(pattern) { yield($~) }
  end
end
class String
  include MDGsub
end

block = proc { |md| p [md.string, *md.captures] }
 ">x".md_gsub(%r!(\W)x!, &block)  # -> [">x", ">"]

I hope that helps for the moment.

Regards
Stefan
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2008-12-11 09:57
Mike Gold wrote:
> Matz suggested that the MatchData could have been passed to the block
> for convenience, however it looks more like a necessity, as I don't see
> a solution short of rewriting gsub.

Here's a solution:

  def meth(replace)
    ">x".gsub(%r!(\W)x!) { |match| replace[$~] }
  end

  replace = lambda { |match|
    puts "match is #{match.inspect}"
    puts "match[1] is #{match[1].inspect}"
  }

  meth(replace)  # => match[1] is ">"
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2008-12-11 11:02
(Received via mailing list)
On Thu, Dec 11, 2008 at 12:18 AM, Mike Gold <mike.gold.4433@gmail.com>
wrote:

> Apparently $1 is bound in a peculiar way:
Not really, it somehow the proc object that is evaluated "first"
def meth(replace)
   ">x".gsub(%r!(\W)x!)do
   puts "$1 is #{$1.inspect}"
   end
 end
and
def meth(replace)
   ">x".gsub(%r!(\W)x!, &replace)
  p $1
 end

work as expected

You will clearly see what I mean with the following example

def meth(replace)
   ">x".gsub(%r!(\W)x!, &replace)
 end

 replace = lambda { |match|
   puts "last_match is #{Regexp.last_match.inspect}"
 }
which produces

last_match is #<MatchData "">

Interesting stuff
Robert




> Posted via http://www.ruby-forum.com/.
>
>



--
Il computer non è una macchina intelligente che aiuta le persone
stupide, anzi, è una macchina stupida che funziona solo nelle mani
delle persone intelligenti.
Computers are not smart to help stupid people, rather they are stupid
and will work only if taken care of by smart people.

Umberto Eco
This topic is locked and can not be replied to.