Issue with: instance_variable_defined?

I expect the third line to be true rather than false.

Comments?

Hal

class SomeClass
      attr_reader :a1, :a2 # Creates @a1, a1, @a2, a2
      attr_writer :b1, :b2 # Creates @b1, b1=, @b2, b2=
      attr_accessor :c1, :c2 # Creates @c1, c1, c1=, @c2, c2, c2=
      # ...
  def initialize
    @c2 = 99
  end
end

obj = SomeClass.new
p obj.instance_variable_defined?(:@c2) # true
p obj.instance_variable_defined?(:@d2) # false
p obj.instance_variable_defined?(:@a2) # false :-/

I was going to say that the attr_* methods don't create instance variables, only the methods to read/write them, as that has been my understanding. But actually, the documentation (at least for attr_reader and attr_accessor) says they _do_ create instance variables.

http://rdoc.info/stdlib/core/1.9.2/Module:attr_accessor

So, I don't know. Perhaps there is a difference in semantics between "create" and "define".

-Justin

···

On 07/13/2011 06:03 PM, Hal Fulton wrote:

I expect the third line to be true rather than false.

Comments?

Hal

class SomeClass
       attr_reader :a1, :a2 # Creates @a1, a1, @a2, a2
       attr_writer :b1, :b2 # Creates @b1, b1=, @b2, b2=
       attr_accessor :c1, :c2 # Creates @c1, c1, c1=, @c2, c2, c2=
       # ...
   def initialize
     @c2 = 99
   end
end

obj = SomeClass.new
p obj.instance_variable_defined?(:@c2) # true
p obj.instance_variable_defined?(:@d2) # false
p obj.instance_variable_defined?(:@a2) # false :-/

The behavior seems correct. The "rb_attr" method in eval.c only creates a reader method and a writer method. It cannot initialize an instance variable since it operates at the class level, not the instance level.

In order to create the behavior you expect, the attr_* methods would have to inject "magic" into the object initialization sequence. That is the only way a class level method could initialize an instance variable for every object instantiated from the class. I do not see any evidence of such magic in the C-level "rb_attr" method.

I believe you are getting a false value correctly.

  p obj.instance_variable_defined?(:@b2) # false
  obj.b2 = 'foo'
  p obj.instance_variable_defined?(:@b2) # true

Since the :a2 accessor is only creating a reader, you will never be able to create an instance variable in the normal fashion ...

  obj.instance_variable_set(:@a2, 'bar')
  p obj.instance_variable_defined?(:@a2) # true

But that is an obvious example to the point of absurdity.

Blessings,
TwP

···

On Jul 13, 2011, at 7:03 PM, Hal Fulton wrote:

I expect the third line to be true rather than false.

Comments?

Hal

class SomeClass
     attr_reader :a1, :a2 # Creates @a1, a1, @a2, a2
     attr_writer :b1, :b2 # Creates @b1, b1=, @b2, b2=
     attr_accessor :c1, :c2 # Creates @c1, c1, c1=, @c2, c2, c2=
     # ...
def initialize
   @c2 = 99
end
end

obj = SomeClass.new
p obj.instance_variable_defined?(:@c2) # true
p obj.instance_variable_defined?(:@d2) # false
p obj.instance_variable_defined?(:@a2) # false :-/