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 :-/

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

   # ...

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 Jul 13, 2011, at 7:03 PM, Hal F. wrote:

 # ...

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