Creating an object from a variable class name

I want to create an object from a class, but the name of that class is
in a variable, so the form obj=Class.new(args) can't be used. How can it
be done? Without using eval, because its a bit messy and unelegant.

The equivalent of obj=$variable_with_class_name(args) in php.

Thanks.
RGR

···

--
Posted via http://www.ruby-forum.com/.

} I want to create an object from a class, but the name of that class is
} in a variable, so the form obj=Class.new(args) can't be used. How can it
} be done? Without using eval, because its a bit messy and unelegant.
}
} The equivalent of obj=$variable_with_class_name(args) in php.

obj = Object::const_get(class_name).new(args)

} Thanks.
} RGR
--Greg

···

On Fri, May 05, 2006 at 03:51:39AM +0900, RGR wrote:

def klass_stamp(hierachy, *a, &b)
         ancestors = hierachy.split(%r/::/)
         parent = Object
         while((child = ancestors.shift))
           klass = parent.const_get child
           parent = klass
         end
         klass::new(*a, &b)
       end

       obj = klass_stamp('String', 'foobar')

-a

···

On Fri, 5 May 2006, RGR wrote:

I want to create an object from a class, but the name of that class is
in a variable, so the form obj=Class.new(args) can't be used. How can it
be done? Without using eval, because its a bit messy and unelegant.

The equivalent of obj=$variable_with_class_name(args) in php.

Thanks.
RGR

--
Posted via http://www.ruby-forum.com/\.

--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama

} I want to create an object from a class, but the name of that class is
} in a variable, so the form obj=Class.new(args) can't be used. How can it
} be done? Without using eval, because its a bit messy and unelegant.
}
} The equivalent of obj=$variable_with_class_name(args) in php.

obj = Object::const_get(class_name).new(args)

mussel:~ > irb -r digest/md5

irb(main):001:0> Digest::MD5.to_s
=> "Digest::MD5"

irb(main):002:0> obj = Object::const_get("Digest::MD5").new(args)
NameError: wrong constant name Digest::MD5
         from (irb):2:in `const_get'
         from (irb):2

it needs to be a bit smarter than that.

regards.

-a

···

On Fri, 5 May 2006, Gregory Seidman wrote:

On Fri, May 05, 2006 at 03:51:39AM +0900, RGR wrote:

         from :0
--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama

And if args is an array you want to use as individual params:

obj = Module.const_get(class_name).new(*args)

(note I prefer Module. but both work)
pth

···

On 5/4/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:

On Fri, May 05, 2006 at 03:51:39AM +0900, RGR wrote:
} I want to create an object from a class, but the name of that class is
} in a variable, so the form obj=Class.new(args) can't be used. How can it
} be done? Without using eval, because its a bit messy and unelegant.
}
} The equivalent of obj=$variable_with_class_name(args) in php.

obj = Object::const_get(class_name).new(args)

} Thanks.
} RGR
--Greg

You know you can do this with inject right?

def klass_stamp(hierachy, *a, &b)
   klass = hierachy.split(/::/).inject(Object) { |parent, child| parent.const_get(child) }
   klass.new(*a, &b)
end

···

On May 4, 2006, at 3:01 PM, ara.t.howard@noaa.gov wrote:

On Fri, 5 May 2006, RGR wrote:

I want to create an object from a class, but the name of that class is
in a variable, so the form obj=Class.new(args) can't be used. How can it
be done? Without using eval, because its a bit messy and unelegant.

The equivalent of obj=$variable_with_class_name(args) in php.

Thanks.
RGR

--
Posted via http://www.ruby-forum.com/\.

      def klass_stamp(hierachy, *a, &b)
        ancestors = hierachy.split(%r/::/)
        parent = Object
        while((child = ancestors.shift))
          klass = parent.const_get child
          parent = klass
        end
        klass::new(*a, &b)
      end

      obj = klass_stamp('String', 'foobar')

-a
--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama

Ara is of course correct, so you end up with something like:

klass = var_with_class.to_s.split('::').inject(Module) { |base,klass|
base.const_get(klass) }
obj = klass.new(*args)

If this is a common operation in your code, you could add this into
Module or some other reasonable place.

pth

···

On 5/4/06, Patrick Hurley <phurley@gmail.com> wrote:

On 5/4/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:
> On Fri, May 05, 2006 at 03:51:39AM +0900, RGR wrote:
> } I want to create an object from a class, but the name of that class is
> } in a variable, so the form obj=Class.new(args) can't be used. How can it
> } be done? Without using eval, because its a bit messy and unelegant.
> }
> } The equivalent of obj=$variable_with_class_name(args) in php.
>
> obj = Object::const_get(class_name).new(args)
>
> } Thanks.
> } RGR
> --Greg
>

And if args is an array you want to use as individual params:

obj = Module.const_get(class_name).new(*args)

(note I prefer Module. but both work)
pth

not on 1.6.8 - which is still the standard redhat-enterprise install.

that code is years and years old anyhow :wink:

-a

···

On Fri, 5 May 2006, Logan Capaldo wrote:

You know you can do this with inject right?

--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama

I understand the ugliness of eval....but why shouldn't we use it? It is
much quicker to write, shorter to read, and easier to use.

···

On Fri, 2006-05-05 at 04:19 +0900, Patrick Hurley wrote:

On 5/4/06, Patrick Hurley <phurley@gmail.com> wrote:
> On 5/4/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:
> > On Fri, May 05, 2006 at 03:51:39AM +0900, RGR wrote:
> > } I want to create an object from a class, but the name of that class is
> > } in a variable, so the form obj=Class.new(args) can't be used. How can it
> > } be done? Without using eval, because its a bit messy and unelegant.
> > }
> > } The equivalent of obj=$variable_with_class_name(args) in php.
> >
> > obj = Object::const_get(class_name).new(args)
> >
> > } Thanks.
> > } RGR
> > --Greg
> >
> >
> >
>
> And if args is an array you want to use as individual params:
>
> obj = Module.const_get(class_name).new(*args)
>
> (note I prefer Module. but both work)
> pth
>

Ara is of course correct, so you end up with something like:

klass = var_with_class.to_s.split('::').inject(Module) { |base,klass|
base.const_get(klass) }
obj = klass.new(*args)

If this is a common operation in your code, you could add this into
Module or some other reasonable place.

pth

No inject in 1.6.8? Gasp!

% cat emergency_inject.rb
module Enumerable
   unless instance_methods.include? "inject"
     def inject(*seed)
       first_item = false
       if seed.empty?
         first_item = true
       else
         seed = seed[0]
       end
       each do |x|
         if first_item
           seed = x
           first_item = false
         else
           seed = yield(seed, x)
         end
       end
       return seed
     end
   end
end

···

On May 4, 2006, at 4:54 PM, ara.t.howard@noaa.gov wrote:

On Fri, 5 May 2006, Logan Capaldo wrote:

You know you can do this with inject right?

not on 1.6.8 - which is still the standard redhat-enterprise install.

that code is years and years old anyhow :wink:

-a
--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama

ruby eval_bench.rb

                user system total real
eval: 1.141000 0.000000 1.141000 ( 1.156000)
const_get: 0.156000 0.000000 0.156000 ( 0.172000)

cat eval_bench.rb

require 'benchmark'
class Foo;end
some_class = 'Foo'
Benchmark.bm(10) do |b|
  b.report("eval:") { 100000.times {eval("#{some_class}.new")} }
  b.report("const_get:") { 100000.times{Object.const_get(some_class).new} }
end

···

On 5/4/06, Charlie Bowman <charlie@castlebranch.com> wrote:

I understand the ugliness of eval....but why shouldn't we use it? It is
much quicker to write, shorter to read, and easier to use.

On Fri, 2006-05-05 at 04:19 +0900, Patrick Hurley wrote:

> On 5/4/06, Patrick Hurley <phurley@gmail.com> wrote:
> > On 5/4/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:
> > > On Fri, May 05, 2006 at 03:51:39AM +0900, RGR wrote:
> > > } I want to create an object from a class, but the name of that class is
> > > } in a variable, so the form obj=Class.new(args) can't be used. How can it
> > > } be done? Without using eval, because its a bit messy and unelegant.
> > > }
> > > } The equivalent of obj=$variable_with_class_name(args) in php.
> > >
> > > obj = Object::const_get(class_name).new(args)
> > >
> > > } Thanks.
> > > } RGR
> > > --Greg
> > >
> >
> > And if args is an array you want to use as individual params:
> >
> > obj = Module.const_get(class_name).new(*args)
> >
> > (note I prefer Module. but both work)
> > pth
> >
>
> Ara is of course correct, so you end up with something like:
>
> klass = var_with_class.to_s.split('::').inject(Module) { |base,klass|
> base.const_get(klass) }
> obj = klass.new(*args)
>
> If this is a common operation in your code, you could add this into
> Module or some other reasonable place.
>
> pth
>

Some would say ugly is reason enough. It's also slower in certain implementations (YARV). The less eval is used, the less it becomes the common case and if it's not the common case it doesn't have to be fast.

···

On May 4, 2006, at 3:57 PM, Charlie Bowman wrote:

I understand the ugliness of eval....but why shouldn't we use it? It is
much quicker to write, shorter to read, and easier to use.

Point taken!

···

On Fri, 2006-05-05 at 05:14 +0900, Wilson Bilkovich wrote:

>ruby eval_bench.rb
                user system total real
eval: 1.141000 0.000000 1.141000 ( 1.156000)
const_get: 0.156000 0.000000 0.156000 ( 0.172000)

>cat eval_bench.rb
require 'benchmark'
class Foo;end
some_class = 'Foo'
Benchmark.bm(10) do |b|
  b.report("eval:") { 100000.times {eval("#{some_class}.new")} }
  b.report("const_get:") { 100000.times{Object.const_get(some_class).new} }
end

On 5/4/06, Charlie Bowman <charlie@castlebranch.com> wrote:
> I understand the ugliness of eval....but why shouldn't we use it? It is
> much quicker to write, shorter to read, and easier to use.
>
> On Fri, 2006-05-05 at 04:19 +0900, Patrick Hurley wrote:
>
> > On 5/4/06, Patrick Hurley <phurley@gmail.com> wrote:
> > > On 5/4/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:
> > > > On Fri, May 05, 2006 at 03:51:39AM +0900, RGR wrote:
> > > > } I want to create an object from a class, but the name of that class is
> > > > } in a variable, so the form obj=Class.new(args) can't be used. How can it
> > > > } be done? Without using eval, because its a bit messy and unelegant.
> > > > }
> > > > } The equivalent of obj=$variable_with_class_name(args) in php.
> > > >
> > > > obj = Object::const_get(class_name).new(args)
> > > >
> > > > } Thanks.
> > > > } RGR
> > > > --Greg
> > > >
> > > >
> > > >
> > >
> > > And if args is an array you want to use as individual params:
> > >
> > > obj = Module.const_get(class_name).new(*args)
> > >
> > > (note I prefer Module. but both work)
> > > pth
> > >
> >
> > Ara is of course correct, so you end up with something like:
> >
> > klass = var_with_class.to_s.split('::').inject(Module) { |base,klass|
> > base.const_get(klass) }
> > obj = klass.new(*args)
> >
> > If this is a common operation in your code, you could add this into
> > Module or some other reasonable place.
> >
> > pth
> >
> >
>
>
>
>

We shouldn't avoid eval just because it takes a second (less on my computer) to use it 100,000 times. In most situations that is premature optimisation.

-- Elliot Temple

···

On May 4, 2006, at 1:14 PM, Wilson Bilkovich wrote:

ruby eval_bench.rb

               user system total real
eval: 1.141000 0.000000 1.141000 ( 1.156000)
const_get: 0.156000 0.000000 0.156000 ( 0.172000)

cat eval_bench.rb

require 'benchmark'
class Foo;end
some_class = 'Foo'
Benchmark.bm(10) do |b|
b.report("eval:") { 100000.times {eval("#{some_class}.new")} }
b.report("const_get:") { 100000.times{Object.const_get(some_class).new} }
end