Projects

Ticket #704 (new defect)

Opened 21 months ago

Last modified 13 months ago

Singleton bug with define_method

Reported by: mike@… Owned by: lsansonetti@…
Priority: major Milestone: MacRuby 1.0
Component: MacRuby Keywords:
Cc:

Description

I'm trying to dynamically add methods to my class in MacRuby. I'm getting a crash in my program. I haven't been able to cut that down to a smaller example yet, but I did find this problem when I tried.

The following program should print this output (and does from Ruby 1.9):

10.0
Float
{"foo"=>10.0}

With MacRuby, it prints

NilClass
{"foo"=>10.0}

If you uncomment the print statement, it starts working. Here's the code

class SingletonTest
  attr_reader :values
  
  def initialize
    @values = {}
  end
  
  def addMethod(name)
    singleton = class << self
      self
    end
    
    singleton.instance_exec(name) do |name|
      define_method("#{name}=") do |value|
        @values[name] = value
      end
      define_method("#{name}") do 
#        puts "returning value"
        return @values[name]
      end
    end
  end

end

singleton_test = SingletonTest.new()
singleton_test.addMethod('foo')

singleton_test.foo = 10.0
value = singleton_test.foo

puts value
puts value.class
puts singleton_test.values

Change History

Changed 14 months ago by jhemmelg@…

It looks like any I/O causes trouble for define_method. Here is a variation of the above script with a puts statement in the assignment method, with different behavior:

class SingletonTest
  attr_reader :values

  def initialize
    @values = {}
  end

  def addMethod(name)
    singleton = class << self
      self
    end

    singleton.instance_exec(name) do |name|
      define_method("#{name}=") do |value|
        puts "Setting #{name} to #{value}"
        @values[name] = value
      end
      define_method("#{name}") do 
        return @values[name]
      end
    end
  end

end

singleton_test = SingletonTest.new()
singleton_test.addMethod('foo')

singleton_test.foo = 10.0
value = singleton_test.foo

puts value
puts value.class
puts singleton_test.values

And here is the output:

Setting foo to 10.0
10.0
Float
{"Setting foo to 10.0"=>10.0}

The hash key ends up being "Setting foo to 10.0" instead of "foo".

Changed 14 months ago by lsansonetti@…

  • milestone set to MacRuby 1.0

Very strange bug. Maybe a bug in the local or instance variables scoping. I think the root cause is unrelated to define_method.

Changed 13 months ago by watson1978@…

It seems that this issue occurs to use the same variable name in argument of #instance_exec and argument of block of #instance_exec.

Test script works when I change it as follows:

    singleton.instance_exec(name) do |m| #  # changed name -> m
      define_method("#{m}=") do |value|
        puts "Setting #{m} to #{value}"
        @values[m] = value
      end
      define_method("#{m}") do
        return @values[m]
      end
    end

I also think this issue is unrelated to define_method.

Note: See TracTickets for help on using tickets.