|
|
 |
 |
 |
 |
Ruby Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
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 -- Posted via http://www.ruby-forum.com/.
On 5/10/07, Bernd <burn@hotmail.com> wrote:
> 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.
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 :)
# 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 :(
# 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 10.05.2007 12:00, Bernd wrote:
> 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.
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 Thursday 10 May 2007 06:00, Bernd wrote:
> 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
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 @. -- Jesse Merriman jessemerri@warpmail.net http://www.jessemerriman.com/
On 5/10/07, Jesse Merriman <jesse.d.merri@gmail.com> wrote:
> On Thursday 10 May 2007 06:00, Bernd wrote: > > 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 > 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 <snip>
HTH Robert -- You see things; and you say Why? But I dream things that never were; and I say Why not? -- George Bernard Shaw
On 5/11/07, Robert Dober <robert.do@gmail.com> 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 <rick.denat@gmail.com> wrote:
> On 5/11/07, Robert Dober <robert.do @gmail.com> 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.
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 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.
Anyway if there was any confusion about the concept you have shed quite some light on it. Cheers Robert -- You see things; and you say Why? But I dream things that never were; and I say Why not? -- George Bernard Shaw
On 2007-05-11 06:58:48 +0900 (Fri, May), Robert Dober wrote:
> On 5/10/07, Jesse Merriman <jesse.d.merri @gmail.com> wrote: > >On Thursday 10 May 2007 06:00, Bernd wrote: > >> 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 > >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
<snip> ..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 ... -- No virus found in this outgoing message. Checked by 'grep -i virus $MESSAGE' Trust me.
|
|
application_pgp-signature_part
1K
Download
|
> ..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 ;) > 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 -- You see things; and you say Why? But I dream things that never were; and I say Why not? -- George Bernard Shaw
|
 |
 |
 |
 |
|