Perplexing difference between debug and normal run of a simp

Please look at this snippet -


class Test

def initialize
@hash = {}
end

def method_missing(m,*a)
if m.to_s =~ /=$/
Test.class_eval do
define_method($.to_sym) do #accessor @hash[$.to_sym]
end
define_method(m) do |arg| #mutator
@hash[$`.to_sym] = arg.split(",")
end
end
send m, *a
else
raise NoMethodError, “#{m}”
end
end
end

t = Test.new
t.a = “hello”
puts t.a


When I run this from the cmdline I get -

D:\sandbox\nasir>ruby test.rb
test.rb:10:in a': undefined methodto_sym’ for nil:NilClass
(NoMethodError)
from test.rb:25

I was unable to debug this so I started the debugger session but I was
surprised to find that it ran as expected in the debugger session ???-


D:\sandbox\nasir>ruby -r debug test.rb
Debug.rb
Emacs support available.

d:/ruby/lib/ruby/site_ruby/1.8/ubygems.rb:10:require ‘rubygems’
(rdb:1) c
hello

First of all can anyone please explain why it runs with debugger while
fails
with normal interpreter?

Second what is wrong with the snippet?

Thanks

On Mon, 2007-01-29 at 14:41 +0900, Nasir K. wrote:

if m.to_s =~ /=$/
  raise NoMethodError, "#{m}"
end

end
end

t = Test.new
t.a = “hello”
puts t.a

[snip]

First of all can anyone please explain why it runs with debugger while fails
with normal interpreter?

Second what is wrong with the snippet?

Perhaps you already know this, but using a local variable in place of $`
fixes your code:

class Test

def initialize
@hash = {}
end

def method_missing(m,*a)
if m.to_s =~ /=$/
key = $` #added here
Test.class_eval do
define_method(key.to_sym) do #accessor
@hash[key.to_sym]
end
define_method(m) do |arg| #mutator
@hash[key.to_sym] = arg.split(",")
end
end
send m, *a
else
raise NoMethodError, “#{m}”
end
end
end

t = Test.new
t.a = “hello,world”
puts t.a

$` is getting clobbered when you go into Test.class_eval so it gets set
to nil. Why this is different to a local variable I’m not sure to be
honest (ditto for why debug mode should be different).

As a related, follow up question, can someone explain the difference
between the two class_evals in the following snippet (one works, the
other doesn’t):

“foo”.match(/oo/)

class Test
end

Test.class_eval do
define_method($.to_sym) do puts $ + “oobared”
end
end
Test.new.f

class Test
class_eval do
define_method($.to_sym) do puts $ + “oobared”
end
end
end