Instance_variables doesn't return unassigned variables

Hi,
I wrote a code like this.

class ABC
attr_accesor :first, :second
end

when I wrote the following:

x = ABC.new
x.first = “test”
puts x.instance_variables

the output was only

@first

Is there a possibility to get also the unassigned variables? I mean,
they exist, but they are only nil.

Thanks so far
Bernd

On 5/10/07, Bernd [email protected] wrote:

x.first = “test”
puts x.instance_variables

the output was only

@first

Is there a possibility to get also the unassigned variables? I mean,
they exist, but they are only nil.

Ruby has no concept of ‘declaring’ instance variables (or any other
variable for that matter). attr_accessor simply generates getter and
setter methods. The instance variable won’t exist in a particular
instance until you call the setter, or directly assign to the instance
variable, such as in the initialize method.

In Ruby, instance variables don’t exist until they are assigned.
Non-existant instance variables evaluate to nil, but just mentioning
them doesn’t bring them into existance.

irb(main):001:0> class A
irb(main):002:1> attr_accessor :i
irb(main):003:1> end
=> nil
irb(main):004:0> a = A.new
=> #<A:0xb7b5aca4>
irb(main):005:0> a.instance_variables
=> []
irb(main):006:0> a.i
=> nil
irb(main):007:0> a.instance_variables
=> []
irb(main):008:0> a.i = “foo”
=> “foo”
irb(main):009:0> a.instance_variables
=> [“@i”]


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Behalf Of Bernd:

class ABC

attr_accesor :first, :second

oops, watch the spell :slight_smile:

end

when I wrote the following:

x = ABC.new

x.first = “test”

puts x.instance_variables

the output was only

@first

sure

Is there a possibility to get also the unassigned variables?

ruby is interpreted and dynamic and, in ruby, everything is an object,
ergo, any object must come to life first. Variables only exist if you
assign them something, or if they refer to something, it’s where they
get their life. We may go the backdoor route by inference…

irb(main):048:0> a=x.public_methods(false).select{|e| e["="]}.map{|e|
“@”+e.chop}
=> ["@second", “@first”]
irb(main):049:0> b=x.instance_variables
=> ["@first"]
irb(main):050:0> a-b
=> ["@second"]

thus @second is not yet vivified …

but i am not sure if i am being rubyish here :frowning:

I mean, they exist, but they are only nil.

careful. there is “exist” vs nil issue here. Eg, a method may return
nil. one may confuse methods with vars.

irb(main):005:0* class ABC
irb(main):006:1> attr_accessor :first, :second
irb(main):007:1> end
=> nil
irb(main):009:0> x=ABC.new
=> #ABC:0xb7d51990
irb(main):010:0> x.first
=> nil
irb(main):015:0> x.instance_variables
=> []
irb(main):016:0> x.first=nil
=> nil
irb(main):017:0> x.first
=> nil
irb(main):018:0> x.instance_variables
=> ["@first"]

at this point @first now exist, but @second is not; ie, from the point
of view of instance x of class ABC.

On Thursday 10 May 2007 06:00, Bernd wrote:

x.first = “test”
puts x.instance_variables

the output was only

@first

You could deduce them by looking for methods that end in an equals:

irb(main):001:0> class ABC
irb(main):002:1> attr_accessor :first, :second
irb(main):003:1> end
=> nil
irb(main):004:0> x = ABC.new
=> #ABC:0xb7a02d48
irb(main):010:0> x.methods.select { |m| /[\w_]+=$/.match m }
=> [“second=”, “first=”]

From there just strip of the = and prepend a @.

On 10.05.2007 12:00, Bernd wrote:

x.first = “test”
puts x.instance_variables

the output was only

@first

Is there a possibility to get also the unassigned variables? I mean,
they exist, but they are only nil.

Additionally to the other replies: you can also do something like this:

irb(main):001:0> Pair = Struct.new :first, :second
=> Pair
irb(main):002:0> Pair.new.members
=> [“first”, “second”]

Kind regards

robert

On 5/10/07, Jesse M. [email protected] wrote:

x = ABC.new
x.first = “test”
puts x.instance_variables

the output was only

@first

You could deduce them by looking for methods that end in an equals:
Hmm that might not be a good idea, a method ending in equals does not
induce the creation of an instance variable with that name.
One could however put attr on steroids by creating a list of
attributes for the class.
Look at this quick and dirty hack do see if this could be helpfull for
you

class Module
alias_method :orig_attreader, :attr_reader
def attr_reader *symbols
@atts ||= superclass.attributes.dup
@atts += symbols
@atts.uniq!
orig_attreader *symbols
end

def attributes
@atts || []
end
end

class A
attr_reader :a
attr_reader :a, :b
puts attributes.join(", ")
end

class B < A
attr_reader :c
def initialize
@c = 42
end
puts attributes.join(", ")
end

puts B.new.c

>

HTH
Robert

…or, since the original problem was that no instance variable has been
created, just create it (in quick and dirty way):
I have not written complicated code because I wanted to write
complicated code :wink:

class Module
alias_method :orig_attr, :attr
def attr(symbol, writable = false)
orig_attr symbol, writable
send symbol
end

The idea is to have attributes and not instance variables, creating
instance variables on the fly with the attr method will not
distinguish them from other instance variables.

I reckon that the only sense I could make from the post was when OP
talked about the instance variables “”“created”"" by the existence of
accessors.
You do that for him, I would think it is worth to distinguish them.
Also have a look at inheritance, which is not handled by your code.

Cheers
Robert

On 2007-05-11 06:58:48 +0900 (Fri, May), Robert D. wrote:

induce the creation of an instance variable with that name.
orig_attreader *symbols
end

def attributes
@atts || []
end
end

…or, since the original problem was that no instance variable has been
created, just create it (in quick and dirty way):

class Module
alias_method :orig_attr, :attr
def attr(symbol, writable = false)
orig_attr symbol, writable
send symbol
end

On 5/11/07, Robert D. [email protected] wrote:

The idea is to have attributes and not instance variables, creating
instance variables on the fly with the attr method will not
distinguish them from other instance variables.

I reckon that the only sense I could make from the post was when OP
talked about the instance variables “”“created”“” by the existence of
accessors.
You do that for him, I would think it is worth to distinguish them.
Also have a look at inheritance, which is not handled by your code.

I’m not sure what the OP was really looking for.

My sense was that there wasn’t a real requirement but a confusion over
why instance variables aren’t created when you ‘declare’ an accessor.

Since the OP doesn’t seem to have posted to this thread since the OP,
I don’t know how much he really cares.

One of the interesting aspects of Ruby as compared to many other OO
languages such as Java, C++ and Smalltalk, is that instance variables
aren’t actually declared, and are really dynamc properties of the
instances themselves rather than all instances of the class.

In the other mentioned languages, declaring instance variables creates
a template which is used to map the storage taken up by an object,
instance variable x is at offset y from the beginning of the object,
etc.

In Ruby instance variables are actually values in a hash which the
instance owns, and are placed there only when code executes which sets
the instance var.

In this way, Ruby is more like Self than those other languages. Self
objects are really just a hash of slot names to slot values. Dave
Ungar used to taunt Smalltalk implementors by asking them to add an
instance variable to the Object class, which usually crashed the
system.

Self went a little farther than Ruby in this regard since it unified
‘instance’ variables and methods, methods are just slots whose values
are executable. In the same regard, all slot values are ‘inheritable’
in the sense that objects can delegate to other objects when searching
for a named slot which is missing, which is how Self gets the effect
of classes, mixins, etc.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On 5/12/07, Rick DeNatale [email protected] wrote:

You do that for him, I would think it is worth to distinguish them.
One of the interesting aspects of Ruby as compared to many other OO
languages such as Java, C++ and Smalltalk, is that instance variables
aren’t actually declared, and are really dynamc properties of the
instances themselves rather than all instances of the class.
So true and that is why I thought that having #instance_variables and
having my little #attributes has nothing to do with each other and
that indeed it might be a good idea to have an introspection tool
concerning the declared attributes of a Class.
I do not even touch instances or instancevariables in my
implementation but I provide a class based attributes introspection
method that respects the inheritance feature of attr_accessor (could
easily be extended for the other attr_* methods of course).

I do not really care if this is what OP wanted, though I thought that
was likely what he or somebody else wanted, I get easily confused, you
know.
Most important I felt that by trying to understand what seemed like a
nonsense request gave me the oppurtunity to do something useful.
Assuming (as dangerous as that might be) that this was what OP or
someone else had in mind.

Sorry if I am talking too many liberties.

In this way, Ruby is more like Self than those other languages. Self
of classes, mixins, etc.
Anyway if there was any confusion about the concept you have shed
quite some light on it.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Cheers
Robert