Dynamic assignment of instance variables

$ cat try.rb
#!/sw/bin/ruby

class Person

attr_accessor :name, :born

def initialize(args)
args.each { |k, v|
self.send “#{k}=”, v
# or: send “#{k}=”, v
}
end

end

p Person.new( :name=> ‘John’, :born=>2003 )

$ try.rb
$ #<Person:0x2a67480 @born=2003, @name=“John”>
$ _

Wished we had something like “self.set(k, v)”. Ruby ri version 1.8b
does not seem to know of such a method, at least not of a method with
such a name.

Is it possible to set instances variables without eval or string
interpolation?

Automatic accessor construction, for example, can be done without the
help of eval and without string interpolation, namely by preceding
"self.send “#{k}=”, v" with

self.class.class_eval { send :attr_accessor, k }

Thanks.

Gerard A.W. Vreeswijk wrote:

Wished we had something like “self.set(k, v)”. Ruby ri version 1.8b
does not seem to know of such a method, at least not of a method with
such a name.

Is it possible to set instances variables without eval or string
interpolation?

irb(main):001:0> class C; end
=> nil
irb(main):002:0> c = C.new
=> #<C:0x4020434c>
irb(main):003:0> c.instance_variable_set(:@x, 1)
=> 1
irb(main):004:0> c
=> #<C:0x4020434c @x=1>

Hi –

···

On Wed, 3 Mar 2004, Gerard A.W. Vreeswijk wrote:

Is it possible to set instances variables without eval or string
interpolation?

#instance_variable_set & …get

(Of course this is separate from the matter of accessor methods,
but you can mix and match as needed.)

David


David A. Black
dblack@wobblini.net

[snip]

Is it possible to set instances variables without eval or string
interpolation?

I can see a couple of ways, so long as the right symbol is passed:

To set instance variables, pass in :@instance_variable symbols
and use #instance_variable_set(sym,val).

class Person
def initialize(args)
args.each do |sym,val|
instance_variable_set(sym,val)
end
end
end
p Person.new(:@name => ‘John’, :@born => ‘2003’)

Using accessors, pass in the :method= symbol and use
send(sym,val):

class Person
attr_accessor :name, :born
def initialize(args)
args.each do |k,v|
send(k,v)
end
end
end
p Person.new(:name= => ‘John’, :born= => ‘2003’)

or if you prefer:

p Person.new(:name==> ‘Fred’, :born==> ‘2004’)

regards,
andrew

···

On 2 Mar 2004 08:16:20 -0800, Gerard A.W. Vreeswijk gv@cs.uu.nl wrote:


Andrew L. Johnson http://www.siaris.net/
It’s kinda hard trying to remember Perl syntax and Occam’s
razor at the same time :slight_smile:
– Graham Patterson

Thanks for pointing out the existence of Object#instance_variable_set
(which, of course, Ruby ri v1.8b knows about).

But then I think Ruby should have a method Object#attribute_set (and
then also a method Object#attribute_get of course), so that we can set
accessible atributes directly so that we are able to say:

Person.new( :name => ‘John’, :born => ‘2003’) # (1)

rather than

Person.new(:@name => ‘John’, :@born => ‘2003’) # (2)

or even

Person.new(:name= => ‘John’, :born= => ‘2003’) # (3)

I this respect, I think it is relevant to quote a 1993 post of Matz [
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/68955 ],
where he says:

Subject: Re: instance_variable_set question
Newsgroups: comp.lang.ruby
Date: 2003-04-09 01:32:15 PST

Hi,

It is a bit confusing, though - if you made an attr_accessor for
@bar,
you refer to it as :bar, not :@bar :

You’re specifying attribute names (i.e. exporting method names),
which
does not contain “@” in them, not instance variable names.
attr_accessor defines methods that use instance variables which names
are “@”+attribute-name.

  matz.

I think a method Object#attribute_set should exist, to enable straight
and dynamic access to attributes when we want to, and to avoid
counterintuitive calls like (2) or (3) in such cases.

What do you think?

Thanks.
Gerard

···

In message “Re: instance_variable_set question” > on 03/04/09, Phil Tomson ptkwt@shell1.aracnet.com writes:

“Gerard A.W. Vreeswijk” gv@cs.uu.nl schrieb im Newsbeitrag
news:d7a05cff.0403040028.33612745@posting.google.com

Thanks for pointing out the existence of Object#instance_variable_set
(which, of course, Ruby ri v1.8b knows about).

But then I think Ruby should have a method Object#attribute_set (and
then also a method Object#attribute_get of course), so that we can set
accessible atributes directly so that we are able to say:

Person.new( :name => ‘John’, :born => ‘2003’) # (1)

rather than

Person.new(:@name => ‘John’, :@born => ‘2003’) # (2)

or even

Person.new(:name= => ‘John’, :born= => ‘2003’) # (3)

I this respect, I think it is relevant to quote a 1993 post of Matz [
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/68955 ],
where he says:

Subject: Re: instance_variable_set question
Newsgroups: comp.lang.ruby
Date: 2003-04-09 01:32:15 PST

Hi,

It is a bit confusing, though - if you made an attr_accessor for
@bar,
you refer to it as :bar, not :@bar :

You’re specifying attribute names (i.e. exporting method names),
which
does not contain “@” in them, not instance variable names.
attr_accessor defines methods that use instance variables which names
are “@”+attribute-name.

  matz.

I think a method Object#attribute_set should exist, to enable straight
and dynamic access to attributes when we want to, and to avoid
counterintuitive calls like (2) or (3) in such cases.

What do you think?

I think that there is a subtle difference between “instance variables” and
“attributes”: an instance variable is a “physical thing”, i.e., an
instance does in fact have a variable defined that carries a value. An
attribute OTOH is something seen from the outside that does not
necessarily relate to an instance variable, although attr, attr_accessor
and the like tend to make people think they are tied together. It’s
perfectly legal to have an attribute that has no 1:1 relationship with an
instance variable:

class Foo
def initialize; @bar = ; end

def size; @bar.size; end

def size=(s)
if s > size
@bar.concat( Array.new(s-size, nil) )
elsif s < size
@bar.slice!(s…-1)
end
end
end

Apart from that someone might have redefined attr, attr_accessor etc. to
generate other methods than the default methods…

So basically, I’d leave it as it is since the naming difference reflects a
semantic difference.

Regards

robert
···

In message “Re: instance_variable_set question” > > on 03/04/09, Phil Tomson ptkwt@shell1.aracnet.com writes:

I think that there is a subtle difference between “instance variables” and
“attributes”: an instance variable is a “physical thing”, i.e., an
instance does in fact have a variable defined that carries a value. An
attribute OTOH is something seen from the outside that does not
necessarily relate to an instance variable, although attr, attr_accessor
and the like tend to make people think they are tied together. It’s
perfectly legal to have an attribute that has no 1:1 relationship with an
instance variable.

I agree. This should be basic Ruby (and perhaps basic OO).

Apart from that someone might have redefined attr, attr_accessor etc. to
generate other methods than the default methods…

That would be no problem I think, because this redefinition would be reflected
in the accessors themselves, i.e., the behaviour of the accessors would
change along.

It’s just that I am too lazy to write the method “attribute_set”
myself AND that this method seems standard enough to be expected as
Ruby built-in method.

Or does my requirement clash with obvious Ruby or OO philosophy?
Please let me know. Thanks.

sh-2.04$ cat try_accessors.rb
class Object

def attribute_set(k, v) # should be built-in
send “#{k}=”, v # interpolation, yuck
end

end

class Person

attr_accessor :name, :born

def initialize(args)
args.each do |attr,val|
attribute_set(attr, val) # should raise an error if attr’s are not settable
end
end

end

p Person.new(:name => ‘John’, :born => ‘2003’)

sh-2.04$ ./try_accessors.rb
#<Person:0x2a876d8 @born=“2003”, @name=“John”>
sh-2.04$ _

···

On Thu, 4 Mar 2004 10:02:44 +0100, “Robert Klemme” bob.news@gmx.net wrote:

This seems like a good idea to me. I’ll add it to the ‘extensions’
project (sorry, no name change yet :slight_smile: unless someone shoots it down.

Cheers,
Gavin

···

On Thursday, March 4, 2004, 9:04:45 PM, Gerard wrote:

class Object
def attribute_set(k, v)
send “#{k}=”, v
end
end

Gavin, do you have a URL? Thanks.

···

On Thu, 4 Mar 2004 19:36:35 +0900, Gavin Sinclair gsinclair@soyabean.com.au wrote:

I’ll add it to the ‘extensions’ project.

http://extensions.rubyforge.org

Gavin

···

On Thursday, March 4, 2004, 10:04:43 PM, Gerard wrote:

On Thu, 4 Mar 2004 19:36:35 +0900, Gavin Sinclair > gsinclair@soyabean.com.au wrote:

I’ll add it to the ‘extensions’ project.

Gavin, do you have a URL? Thanks.

Gavin Sinclair wrote:

···

On Thursday, March 4, 2004, 10:04:43 PM, Gerard wrote:

On Thu, 4 Mar 2004 19:36:35 +0900, Gavin Sinclair >>gsinclair@soyabean.com.au wrote:

I’ll add it to the ‘extensions’ project.

Gavin, do you have a URL? Thanks.

http://extensions.rubyforge.org

Gavin

Hey you know you could stuff prime? as a method in Integer as well.
Just run a miller-rabin primality test. I’ll see if I can’t cook up
some code for that and send it your way, it might be another interesting
extension to have.

Charlie

“Charles Comstock” cc1@cec.wustl.edu schrieb im Newsbeitrag
news:c278e5$c4g$1@newsreader.wustl.edu…

Gavin Sinclair wrote:

I’ll add it to the ‘extensions’ project.

Gavin, do you have a URL? Thanks.

http://extensions.rubyforge.org

Gavin

Hey you know you could stuff prime? as a method in Integer as well.
Just run a miller-rabin primality test. I’ll see if I can’t cook up
some code for that and send it your way, it might be another interesting
extension to have.

IMHO it’s better to have a PrimeTester class that does the checking
because for efficiency reasons I’d want to store detected prime numbers
somewhere. Just my 0.02 EUR.

robert
···

On Thursday, March 4, 2004, 10:04:43 PM, Gerard wrote:

On Thu, 4 Mar 2004 19:36:35 +0900, Gavin Sinclair > >>gsinclair@soyabean.com.au wrote:

Yeah, sounds nice. I’d be a little concerned about performance
though. Although that’s prejedging; show me what you’ve got :slight_smile:

Cheers,
Gavin

···

On Thursday, March 4, 2004, 11:49:42 PM, Charles wrote:

http://extensions.rubyforge.org

Hey you know you could stuff prime? as a method in Integer as well.
Just run a miller-rabin primality test. I’ll see if I can’t cook up
some code for that and send it your way, it might be another interesting
extension to have.

“Charles Comstock” cc1@cec.wustl.edu schrieb im Newsbeitrag
news:c278e5$c4g$1@newsreader.wustl.edu…

Hey you know you could stuff prime? as a method in Integer as well.
Just run a miller-rabin primality test. I’ll see if I can’t cook up
some code for that and send it your way, it might be another
interesting
extension to have.

IMHO it’s better to have a PrimeTester class that does the checking
because for efficiency reasons I’d want to store detected prime numbers
somewhere. Just my 0.02 EUR.

Why not store it in the number itself?

23.instance_eval{@prime = true}
=> true
24.instance_eval{@prime = false}
=> false
23.instance_eval{@prime}
=> true
24.instance_eval{@prime}
=> false

Or were you meaning persistant storage, so that it would be available
to other interpreters?

–Mark

···

On Mar 4, 2004, at 5:04 AM, Robert Klemme wrote:

Mark Hubbart wrote:

Why not store it in the number itself?

23.instance_eval{@prime = true}
=> true
24.instance_eval{@prime = false}
=> false
23.instance_eval{@prime}
=> true
24.instance_eval{@prime}
=> false

Or were you meaning persistant storage, so that it would be available to
other interpreters?

When did this start working? :slight_smile: This seems to be a good step
toward singletons for Fixnums (unless those are already working
also, and I haven’t noticed).

Hal

“Mark Hubbart” discord@mac.com schrieb im Newsbeitrag
news:154A61B0-6E0E-11D8-A7C0-000502FDD5CC@mac.com

“Charles Comstock” cc1@cec.wustl.edu schrieb im Newsbeitrag
news:c278e5$c4g$1@newsreader.wustl.edu…

Hey you know you could stuff prime? as a method in Integer as well.
Just run a miller-rabin primality test. I’ll see if I can’t cook up
some code for that and send it your way, it might be another
interesting
extension to have.

IMHO it’s better to have a PrimeTester class that does the checking
because for efficiency reasons I’d want to store detected prime
numbers
somewhere. Just my 0.02 EUR.

Why not store it in the number itself?

Because prime number testing

(a) tends to be slow due to its complexity

(b) there are several algorithms AFAIK with no standard that is best under
all circumstances

(c) because of (a) typically you calculate the property only once for each
number and thus have to store the result somewhere.

(d) you have to take care of concurrency issues when implementing it in
Number or Integer because multiple threads may try to get the prime?
property of the same number at the same time and numbers are used all over
the place (i.e. high likelyhood of concurrent usage of the same number
instance)

All in all prime number testing is a complex thing (although, looking from
the boolean outcome, it looks simple) that doesn’t easily fit into a
standard implementation of basic number handling IMHO.

23.instance_eval{@prime = true}
=> true
24.instance_eval{@prime = false}
=> false
23.instance_eval{@prime}
=> true
24.instance_eval{@prime}
=> false

That’s possible, true.

Or were you meaning persistant storage, so that it would be available
to other interpreters?

Nope.

Kind regards

robert
···

On Mar 4, 2004, at 5:04 AM, Robert Klemme wrote:

When did this start working? :slight_smile: This seems to be a good step
toward singletons for Fixnums (unless those are already working
also, and I haven’t noticed).

23.instance_eval {@prime = true}
=> true
24.instance_eval {@prime = false}
=> false
23.instance_eval {@prime}
=> true
24.instance_eval {@prime}
=> false
RUBY_VERSION
=> “1.6.8”

1.6.x is the earliest version I’ve worked with… I remember trying
this when I first started out with ruby :slight_smile: I thought it was a nifty
trick. You still can’t define singleton methods though, just add
instance variables. Though, I suppose you could add a proc object as an
instance variable.

···

On Mar 4, 2004, at 12:04 PM, Hal Fulton wrote:

Mark Hubbart wrote:

···

On Mar 4, 2004, at 12:04 PM, Hal Fulton wrote:

When did this start working? :slight_smile: This seems to be a good step
toward singletons for Fixnums (unless those are already working
also, and I haven’t noticed).

23.instance_eval {@prime = true}
=> true
24.instance_eval {@prime = false}
=> false
23.instance_eval {@prime}
=> true
24.instance_eval {@prime}
=> false
RUBY_VERSION
=> “1.6.8”

1.6.x is the earliest version I’ve worked with… I remember trying this
when I first started out with ruby :slight_smile: I thought it was a nifty trick.
You still can’t define singleton methods though, just add instance
variables. Though, I suppose you could add a proc object as an instance
variable.

The last time I tried this, it was a little deceptive. A variable
that you added to one Fixnum was the same for all Fixnums.

Hal

Hal Fulton wrote:

1.6.x is the earliest version I’ve worked with… I remember trying
this when I first started out with ruby :slight_smile: I thought it was a nifty
trick. You still can’t define singleton methods though, just add
instance variables. Though, I suppose you could add a proc object as
an instance variable.

The last time I tried this, it was a little deceptive. A variable
that you added to one Fixnum was the same for all Fixnums.

Well with 1.8.1 you get

···

class Fixnum
def bla=(rhs)
@bla = rhs
end
def bla
p @bla
end
end

2.bla = true
3.bla = false

2.bla # true

/Christoph