lambda with $1 fails as gsub block

M

Mike Gold

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...6ea75e5de/0211d0b304cbbad0?hl=enÓd0b304cbbad0

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?
 
S

Stefan Rusterholz

Mike said:
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
 
B

Brian Candler

Mike said:
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 ">"
 
R

Robert Dober

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 =3D lambda { |match|
puts "last_match is #{Regexp.last_match.inspect}"
}
which produces

last_match is #<MatchData "">

Interesting stuff
Robert



http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/e24a1= 9e6ea75e5de/0211d0b304cbbad0?hl=3Den%C3%93d0b304cbbad0

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?



--=20
Il computer non =E8 una macchina intelligente che aiuta le persone
stupide, anzi, =E8 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top