Forum: Ruby Dumb reflection problem - create object from String

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
44262058c9f30942c2f1ffbf3b512142?d=identicon&s=25 Brian Parkinson (Guest)
on 2006-04-09 20:14
Hello - I'm bashing my head against the wall - I'm sure this is a simple
question, but damned if I can figure it out.

If I have a String which corresponds to a class name, how do I create an
instance of this class?

Example:

class MyExampleClass
    ...
end

s = 'MyExampleClass'

# We want to instantiate a new instance of the class
myExampleClassInstance = ???

I want the behaviour of 'MyExampleClass.new' but only using the String
value of s.

I'm sure it's a one-liner.

Any help appreciated.

Thanks.

parki...
C85a33334dbbf2b23c87e8fa78beb8d2?d=identicon&s=25 Sven Klemm (Guest)
on 2006-04-09 20:26
(Received via mailing list)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Brian Parkinson wrote:
> end
>
> s = 'MyExampleClass'
>
> # We want to instantiate a new instance of the class
> myExampleClassInstance = ???
>
> I want the behaviour of 'MyExampleClass.new' but only using the String
> value of s.

Have a look at Module.const_get

Module.const_get(s).new

HTH,
Sven

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (FreeBSD)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEOVItevlgTHEIT4YRAl3wAJ4j4zJTlcMR9A8ZJKixHXvig0eGywCfUPGN
W26rak8DMs/szMC+niiVvds=
=8+ZL
-----END PGP SIGNATURE-----
733436f59b64e31c1dd78fc0d29f3cdb?d=identicon&s=25 Gyoung-Yoon Noh (Guest)
on 2006-04-09 20:29
(Received via mailing list)
On 4/10/06, Brian Parkinson <parkI@whatevernot.com> wrote:
> end
>
>
$ irb
irb(main):001:0> class K
irb(main):002:1> end
=> nil
irb(main):003:0> k1 = K.new
=> #<K:0xb7fc1788>
irb(main):004:0> k2 = eval('K').new
=> #<K:0xb7fb8094>
irb(main):005:0> k3 = Object.const_get('K').new
=> #<K:0xb7fb1474>
44262058c9f30942c2f1ffbf3b512142?d=identicon&s=25 Brian Parkinson (Guest)
on 2006-04-09 20:30
Sven Klemm wrote:

[deletia]

> Module.const_get(s).new

Thanks!

I knew it would be a one-liner. :-)

parki...
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2006-04-09 21:06
(Received via mailing list)
DÅ?a Nedeľa 9. Apríl 2006 20:26 Gyoung-Yoon Noh napísal:
> >     ...
> > I'm sure it's a one-liner.
>
>
> --
> http://nohmad.sub-port.net

I would, naively hoping to see YARV released Sometime Soon (tm), rather
use
<anything but eval>, since it probably is / will be easier for YARV to
work
with <anything but eval>, as far as optimizations are concerned. It also
makes the intent of the code clearer.

David Vallner
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2006-04-09 21:25
(Received via mailing list)
On 4/9/06, Brian Parkinson <parkI@whatevernot.com> wrote:
>
> parki...


I am afraid that the only  one-liner is eval :(

suppose s contains the name of your class
Module.const_get s does not work unless your class is defined on top
level.
In oder to have the *same* semantics as

   eval(s).new

we have to write

m = Module
s.split(%r{::|\.}).each do
    |name|
    m = m.const_get(name)
end
m.new

I suggest to look at ObjectSpace for another alternative, hardly more
efficent though :(

Robert


--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-04-09 21:43
(Received via mailing list)
On Apr 9, 2006, at 3:21 PM, Robert Dober wrote:

>> I knew it would be a one-liner. :-)
>
>
> - Albert Einstein
s.split(/::/).inject(Object) { |p, c| p.const_get(c) }.new

There, a one liner (w/o any semi-colons)
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-04-09 21:45
Robert Dober wrote:
> On 4/9/06, Brian Parkinson <parkI@whatevernot.com> wrote:
>>
>> parki...
>
>
> I am afraid that the only  one-liner is eval :(
>
> suppose s contains the name of your class
> Module.const_get s does not work unless your class is defined on top
> level.
> In oder to have the *same* semantics as
>
>    eval(s).new
>
> we have to write
>
> m = Module
> s.split(%r{::|\.}).each do
>     |name|
>     m = m.const_get(name)
> end
> m.new

  s.split('::').inject(Object) { |s,k| s.const_get(k) }.new

-- Jim Weirich
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2006-04-09 22:08
(Received via mailing list)
On 4/9/06, Logan Capaldo <logancapaldo@gmail.com> wrote:
> >>> Module.const_get(s).new
> > suppose s contains the name of your class
> >     |name|
> > --
> Yup, very nice
What I meant though is that eval seems much simpler and cheaper
Let us see
yet your's is fine, just look at the mess when searching through
ObjectSpace

cat perf.rb; ruby perf.rb
require 'benchmark'

module One
  class Two
    class Three
    end
  end
end
s="One::Two::Three"
n = 50000
Benchmark.bm do |x|
  x.report("eval       "){ n.times{ eval(s).new } }
  x.report("split      ") { n.times{ s.split(/::/).inject(Object) { |p,
c|
p.const_get(c) }.new } }
  x.report("ObjectSpace"){n.times{x=nil;ObjectSpace.each_object(Class){|cls|
x=cls if
cls.to_s == s};x.new } }
end      user     system      total        real
eval         0.280000   0.000000   0.280000 (  0.372346)
split        0.540000   0.000000   0.540000 (  0.621870)
ObjectSpace 21.920000   0.070000  21.990000 ( 24.452318)


--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein
This topic is locked and can not be replied to.