Hi there!
The following spec does not pass on rbx (in
spec/ruby/core/kernel/gsub_spec.rb#78):
describe "Kernel#gsub with pattern and block" do
it "acts similarly to using $_.gsub" do
$_ = "olleh dlrow"
gsub(/(\w+)/){ $1.reverse }
$_.should == "hello world"
end
end
Trying to fix this one, I found that there is a comparison of replacement (in this case it is nil, because gsub is passed a block instead of a replacement string) with undefined, which always evaluates to false (even if it is nil). Since I don't know really well what `undefined` is, I've first tried comparing replacement to nil, which seems to work (in kernel/common/string.rb#902):
def gsub(pattern, replacement=undefined)
# ...
if replacement.nil? # was if replacement == undefined
Now the problem is that, when evaling the block { $1.reverse }, $1 is nil. Upon further inspection, This happens just before evaling the block, where Regexp's last match is (unsuccessfully) set to the intended match data (same file, #939):
if use_yield
# Although `match` contains actual match data,
Regexp.last_match = match
# Here Regexp.last_match is nil.
# So this block evaluation will fail when trying to do nil.reverse
val = yield(match.to_s)
I've tried it in the rbx console, so it seems Regexp.last_match=(matchdata) (although it returns the passed matchdata) does nothing to Regexp.last_match (it keeps previous matched data, or nil if it was nil).
I've checked the regexp.cpp file but I'm no expert there, so I can't tell what's wrong....
Any thoughts?