How to test for existence of instance variable?

I have an existing class Foo, and existing objects of that class.

I now extend the class by adding a method, which makes use of an instance
variable which previously did not exist.

How can I make it test that the instance variable is uninitialised, so I can
prevent a warning? This is what I am trying to do:

class Foo
attr_reader :things
def add_thing(n)
if @things.nil?
@things = []
end
@things << n
end
end

However, the test ‘@things.nil?’ generates
’warning: instance variable @things not initialized’
if ruby is running with -w. (This is 1.6.8)

I am hoping that I don’t have to keep track of all existing Foo objects,
just so that I can send them a message ‘reset_things’

Thanks…

Brian.

How can I make it test that the instance variable is uninitialised, so I can
prevent a warning? This is what I am trying to do:

class Foo
attr_reader :things
def add_thing(n)
if @things.nil?
@things =
end
@things << n
end
end

However, the test ‘@things.nil?’ generates
‘warning: instance variable @things not initialized’
if ruby is running with -w. (This is 1.6.8)

I am hoping that I don’t have to keep track of all existing Foo objects,
just so that I can send them a message ‘reset_things’

class A
def add_thing
@foo ||= ‘test’
end
attr_reader :foo
end
=> nil
A.new.foo
(irb):7: warning: instance variable @foo not initialized
=> nil
a = A.new
=> #<A:0x4021d7c8>
a.add_thing
=> “test”
a.foo
=> “test”

···

On Tue, Feb 18, 2003 at 03:33:53AM +0900, Brian Candler wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

  • LG loves czech girls.
    LG: do they have additional interesting “features” other girls don’t have? :wink:
    #Debian
> How can I make it test that the instance variable is uninitialised, so > I can prevent a warning? This is what I am trying to do:

With “defined?” like any other variable:

class Foo
attr_reader :things
def add_thing(n)

if not defined? @things

    @things = [] 
  end
  @things << n
end

end

···

On Tue, 18 Feb 2003 03:33:53 +0900 Brian Candler B.Candler@pobox.com wrote:


Ryan Pavlik rpav@users.sf.net

“You mean easily pawned valuable crystal orb thingie.” - 8BT

In article 20030217183329.A78444@linnet.org,

I have an existing class Foo, and existing objects of that class.

I now extend the class by adding a method, which makes use of an instance
variable which previously did not exist.

How can I make it test that the instance variable is uninitialised, so I can
prevent a warning? This is what I am trying to do:

class Foo
attr_reader :things
def add_thing(n)
if @things.nil?
@things =
end
@things << n
end
end

However, the test ‘@things.nil?’ generates
‘warning: instance variable @things not initialized’
if ruby is running with -w. (This is 1.6.8)

If I understand what you’re trying to do, then you need to test to see if
@things is defined, like:

if defined?(@things)
@things << n
else
@things =
end

Phil

···

Brian Candler B.Candler@pobox.com wrote:

Brian Candler B.Candler@pobox.com writes:

I have an existing class Foo, and existing objects of that class.

I now extend the class by adding a method, which makes use of an
instance variable which previously did not exist.

How can I make it test that the instance variable is uninitialised,
so I can prevent a warning? This is what I am trying to do:

class Foo
attr_reader :things
def add_thing(n)
if @things.nil?
@things =
end
@things << n
end
end

This won’t generate a warning.

def add_thing(n)
    @thing ||= []
    @thing << n
end
···


matt

Hi,

How can I make it test that the instance variable is uninitialised, so I can
prevent a warning?

I think defined? might do the trick:

class Foo
def initialize
p defined? @bar
@bar = 123
p defined? @bar
end
end
=> nil
Foo.new
nil # the result of the 1st defined? test
“instance-variable” # the result of the 2nd
=> #<Foo:0x2ab9b70 @bar=123>

HTH,

Bill

···

From: “Brian Candler” B.Candler@pobox.com

Doh, how did I miss that! I keep looking at the class reference and forget
that there are actually some reserved words in the language as well :slight_smile:

Thanks to everyone.

B.

···

On Tue, Feb 18, 2003 at 05:39:34AM +0900, Bill Kelly wrote:

I think defined? might do the trick:

>> class Foo
>> def initialize
>> p defined? @bar
>> @bar = 123
>> p defined? @bar

OK, how about this one :slight_smile:

I have a Struct, and have dynamically added a new member.

I want to check whether the instance variable corresponding to that
attribute is already initialised. How can I do that? Example:

  foo = Struct.new("Foo", "a", "b", "c")
  obj = foo.new

  newmember="d"
  foo.module_eval { attr_accessor newmember }

  obj.send("#{newmember}=", ) if obj.send(newmember).nil? # ***
  obj.send(newmember)<< "hello"
  puts obj.send(newmember)

How can I write the line '***' so it does not generate a warning under -w ?
Note that 'respond_to?' is not the answer, because the accessor methods do
exist - it's just the associated instance variable which has not been
initialised.

Cheers,

Brian.

···

On Mon, Feb 17, 2003 at 10:46:59AM -0800, Bill Kelly wrote:

> How can I make it test that the instance variable is uninitialised, so I can
> prevent a warning?

I think defined? might do the trick:

I want to check whether the instance variable corresponding to that
attribute is already initialised.

First test if the instance variable exist.

Guy Decoux

Hi,

···

In message “Re: How to test for existence of instance variable?” on 03/02/18, Brian Candler B.Candler@pobox.com writes:

How can I write the line ‘***’ so it does not generate a warning under -w ?

Attribute readers should not report warning for uninitialized instance
variables. I will fix.

						matz.

> I want to check whether the instance variable corresponding to that
> attribute is already initialised.
   
First test if the instance variable exist.

That was essentially what I was asking. What is the way to check if an
instance variable exists, when its name is dynamic? Preferably not something
incredibly inefficient like

   obj.instance_eval "defined? @#{newmember}"

(since all I'm trying to do is avoid a warning).

Regards,

Brian.

That was essentially what I was asking. What is the way to check if an
instance variable exists, when its name is dynamic? Preferably not something
incredibly inefficient like

#instance_variables give you the name of all instance variables for an
object.

Guy Decoux

Why should this be fixed? The warning looks reasonable to me.

Paul

···

On Tue, Feb 18, 2003 at 09:52:12PM +0900, Yukihiro Matsumoto wrote:

Hi,

In message “Re: How to test for existence of instance variable?” > on 03/02/18, Brian Candler B.Candler@pobox.com writes:

How can I write the line ‘***’ so it does not generate a warning under -w ?

Attribute readers should not report warning for uninitialized instance
variables. I will fix.

Hi,

···

In message “Re: How to test for existence of instance variable?” on 03/02/19, Paul Brannan pbrannan@atdesk.com writes:

How can I write the line ‘***’ so it does not generate a warning under -w ?

Attribute readers should not report warning for uninitialized instance
variables. I will fix.

Why should this be fixed? The warning looks reasonable to me.

Because it’s non intuitive. There’s no logical relationship between
an attribute reader “foo” and an instance variable “@foo” to the
users.

						matz.

Creating an attribute reader and not initializing the attribute (either
with @foo= or with self.foo=) is a bug. The user should never see this
warning except for buggy code.

Paul

···

On Wed, Feb 19, 2003 at 02:08:07AM +0900, Yukihiro Matsumoto wrote:

In message “Re: How to test for existence of instance variable?” > on 03/02/19, Paul Brannan pbrannan@atdesk.com writes:

Why should this be fixed? The warning looks reasonable to me.

Because it’s non intuitive. There’s no logical relationship between
an attribute reader “foo” and an instance variable “@foo” to the
users.

What Paul says makes sense to me.

Hal

···

----- Original Message -----
From: “Paul Brannan” pbrannan@atdesk.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, February 18, 2003 2:19 PM
Subject: Re: How to test for existence of instance variable?

On Wed, Feb 19, 2003 at 02:08:07AM +0900, Yukihiro Matsumoto wrote:

In message “Re: How to test for existence of instance variable?” > > on 03/02/19, Paul Brannan pbrannan@atdesk.com writes:

Why should this be fixed? The warning looks reasonable to me.

Because it’s non intuitive. There’s no logical relationship between
an attribute reader “foo” and an instance variable “@foo” to the
users.

Creating an attribute reader and not initializing the attribute (either
with @foo= or with self.foo=) is a bug. The user should never see this
warning except for buggy code.

Hi,

···

In message “Re: How to test for existence of instance variable?” on 03/02/19, Paul Brannan pbrannan@atdesk.com writes:

Creating an attribute reader and not initializing the attribute (either
with @foo= or with self.foo=) is a bug. The user should never see this
warning except for buggy code.

I thought it is needed just because

@foo ||=

trick cannot be done for attributes without causing warning.

						matz.

Well I’d agree, except what happens if you add an attribute to a class which
has existing members? In other words, I’d like to do

 struct.member ||= []           # initialise to empty array if needed
 struct.member << something     # add a value

without generating a warning, but I can’t seem to do this if the member was
added to the structure since the object was first created. The object
already exists, so its initialize method won’t be called of course.

#!/usr/local/bin/ruby -w
mystruct = Struct.new(“Mystruct”,“a”,“b”,“c”)
obj = mystruct.new

mystruct.instance_eval { attr_accessor :d } # add a new member

obj.d ||=
obj.d << “hello”

This generates:
foo.rb:7: warning: instance variable @d not initialized

and I can’t see an obvious way to get around the problem.

Regards,

Brian.

···

On Wed, Feb 19, 2003 at 05:19:15AM +0900, Paul Brannan wrote:

Creating an attribute reader and not initializing the attribute (either
with @foo= or with self.foo=) is a bug. The user should never see this
warning except for buggy code.

i don’t consider something like this ‘buggy’

class File
attr_reader :locked

def lock
  @locked = true
end

end

f = File.new
f.locked # → false (nil)
f.lock
f.locked # → true

IHMO it is tiresome to require

def initialize

@locked = true

end

for every instance variable which may be used.

besides, you may start out with

class Klass
attr_accessor :var
end

but later move to

class Klass
def var

end
def var= v

end
end

i think this is what matz means by ‘no logical relationship’, eg. a user
should never KNOW that ob.var implies ob’s @var and thus the error message is
non intuitive. this is obviously not the case as developers of a class, but
the error messages are not for us (only)…

-a

···

On Wed, 19 Feb 2003, Hal E. Fulton wrote:

----- Original Message -----
From: “Paul Brannan” pbrannan@atdesk.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, February 18, 2003 2:19 PM
Subject: Re: How to test for existence of instance variable?

On Wed, Feb 19, 2003 at 02:08:07AM +0900, Yukihiro Matsumoto wrote:

In message “Re: How to test for existence of instance variable?” > > > on 03/02/19, Paul Brannan pbrannan@atdesk.com writes:

Why should this be fixed? The warning looks reasonable to me.

Because it’s non intuitive. There’s no logical relationship between
an attribute reader “foo” and an instance variable “@foo” to the
users.

Creating an attribute reader and not initializing the attribute (either
with @foo= or with self.foo=) is a bug. The user should never see this
warning except for buggy code.

What Paul says makes sense to me.
Hal

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

Hi,

Creating an attribute reader and not initializing the attribute (either
with @foo= or with self.foo=) is a bug. The user should never see this
warning except for buggy code.

I thought it is needed just because

@foo ||=

trick cannot be done for attributes without causing warning.

???

batsman@tux-chan:/tmp$ irb --simple-prompt
/usr/lib/ruby/1.6/irb/context.rb:112: warning: method redefined; discarding old irb_name
/usr/lib/ruby/1.6/irb/context.rb:176: warning: method redefined; discarding old math_mode=
/usr/lib/ruby/1.6/irb/context.rb:188: warning: method redefined; discarding old use_readline=
/usr/lib/ruby/1.6/irb/context.rb:177: warning: instance variable @math_mode not initialized
/usr/lib/ruby/1.6/irb/context.rb:151: warning: instance variable @use_tracer not initialized

class A; def foo; @foo ||= ; end; end
=> nil
A.new.foo
=>

If you mean that attr_* won’t work with default values, we can use
something like the following:

batsman@tux-chan:/tmp$ set | grep RUBYOPT
RUBYOPT=-w
batsman@tux-chan:/tmp$ expand -t 2 z.rb

module AttrWithDefault
def attr_reader_with_default(sym, val)
instance_eval <<-EOF
class << self
attr_accessor “#{sym.to_s}”.intern
attr_reader :symlist
end
@symlist ||=
@symlist.push( [self, “#{sym}”] )
EOF
meth = self.method “#{sym.to_s}=”.intern
meth.call( val )

module_eval <<-EOF
def #{sym.to_s}
  @#{sym.to_s} ||= self.class._#{sym.to_s}_
end
EOF

if self.singleton_methods.grep("inherited") == []
  class << self
    def inherited sub
      ancestors.each do |klass|
        begin
          assoc = klass.__symlist__
          assoc.each do |x|
            #puts "Redefining #{x[1]} from #{sub} using #{x[0]}._#{x[1]}_"
            sub.module_eval <<-EOF
            def #{x[1]}
              @#{x[1]} ||= #{x[0]}._#{x[1]}_
            end
            EOF
          end
        rescue NameError
        end
      end
    end
  end
end

end
end

class A
extend AttrWithDefault
attr_reader_with_default :foo,
attr_reader_with_default :bar, ‘test’

def inspect
str = “#{self.class}:”
instance_variables.each do |iv|
str << " #{iv} => "
str << instance_eval(“#{iv}”).inspect
end
str
end
end

a = A.new
p a
a.foo
p a

class B < A
attr_reader_with_default :bar2, ‘bla’
end

class C < B
end

b = B.new
p b
b.foo
b.bar
p b

c = C.new
p c
c.foo
c.bar
c.bar2
p c
batsman@tux-chan:/tmp$ ruby z.rb
A:
B:
B: @bar => “test” @foo =>
C:
C: @bar => “test” @bar2 => “bla” @foo =>

I am not sure about what default value to take when several are
specified at different points along the inheritance chain.

···

On Wed, Feb 19, 2003 at 05:08:19PM +0900, Yukihiro Matsumoto wrote:

In message “Re: How to test for existence of instance variable?” > on 03/02/19, Paul Brannan pbrannan@atdesk.com writes:
A: @foo =>


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Sigh. I like to think it’s just the Linux people who want to be on
the “leading edge” so bad they walk right off the precipice.
– Craig E. Groeschel