Dynamic classes

So I am working on some metaprograming and have some questions about
how to get what I need out of dynamic classes.

Right now I know I can define dynamic classes like so:
a) TestClass = Class.new
b) var_class = Class.new

These work as expected but I need the functionality provided by case
A. Specifically I need to have the instances respond to .class
appropriately. .class for case B returns Class, while case A responds
TestClass

The reason I need to do this is that I want to dynamically generate
classes, including their names. How can I accomplish this?

My desired results:

variable = Class.new
variable.class.name == ‘variable’

OR, I need to be able to assign a dynamic constant name (I know I
know).

Any help would be appreciated.

On Mar 25, 10:21am, PsiPro [email protected] wrote:

TestClass
know).

Any help would be appreciated.

So I figured it out on my own, but still need some feedback.

Running
x=“Foo”
c = eval(“ClassNamePrefix#{x} = Class.new”)

provided the desired results. I don’t like the idea of using eval if
at all possible tho, any feedback would be greatly appreciated.

Thank you.

You can give it a dynamic name with eval:

ruby-1.9.2-p180 > a = “Monkey”
=> “Monkey”
ruby-1.9.2-p180 > eval("#{a} = Class.new")
=> Monkey
ruby-1.9.2-p180 > b = Monkey.new
=> #Monkey:0x00000100b37f80
ruby-1.9.2-p180 >

It seemed a bit messy so I checked out also Class.new, Module.new and
Module.name ( class inherits from module and hence uses the name
property) but no luck :frowning:

I wonder whyClass.new and Module.new don’t have a parameter to define
the name (seems something a person would want to do). Any ideas ?

Regards,
V.

On Fri, Mar 25, 2011 at 3:25 PM, PsiPro [email protected] wrote:

TestClass
Case b cannot return Class. You would rather see something like this:

16:10:04 ~$ ruby19 -e ‘TestClass = Class.new; p TestClass.new.class;
var_class = Class.new; p var_class.new.class’
TestClass
#Class:0x1003b03c

The reason I need to do this is that I want to dynamically generate
classes, including their names. How can I accomplish this?

My desired results:

variable = Class.new
variable.class.name == ‘variable’

Magic works only with constants. The first constant that a Class or
Module instance is assigned determines its name.

OR, I need to be able to assign a dynamic constant name (I know I
know).

16:30:47 ~$ ruby19 -e ‘x=Class.new;Object.const_set(“Foo”,x);p x,
x.new.class’
Foo
Foo

Why do you need this? Maybe you can do

classes = {}

classes[“Foo”] = Class.new do
def nifty_method
42
end
end

Now you can do

obj = classes[“Foo”].new

You could even override Class#name or #to_s per instance to return the
proper value, if you must have the class name…

Cheers

robert

My desired results:

variable = Class.new
variable.class.name == ‘variable’

Are you sure about that? ‘variable’ is a class object just like MyClass
is a class object in the following code:

class MyClass
def greet
puts ‘hi’
end
end

Because ‘variable’ is a class object, its class is Class, and the name
of the Class class is not ever going to be ‘variable’–it’s going to be
‘Class’:

puts MyClass.class.name

–output:–
Class

Vicente B. Campos wrote in post #989219:

I wonder why Class.new and Module.new don’t have a parameter to define
the name (seems something a person would want to do). Any ideas ?

Because you have to assign the newly created class object to a
variable–otherwise it will be discarded, just like all values that
aren’t assigned to a variable are discarded. If you want to name the
class, you can assign the newly created class to a constant, i.e. a name
that is capitalized. Then the class will take on the name of the
constant. If you assign the class object to a regular variable it won’t
have a name–it will be anonymous:

x = Class.new do
def greet
puts ‘hi’
end
end

puts “–> #{x.name} <–”

–output:–
–> <–

MyClass = x #now MyClass and x both refer to the same object
puts x.name

–output:–
MyClass

On 26.03.2011 15:38, Vicente B. Campos wrote:

I understand how it works at the moment. Still if you are doing
metaprogramming and consider with a very purist perspective that
everything is an object then a Class definition is just an instance
of the Class Class

The definition is a definition, the result of executing it is an
instance of class Class.

and I should be able to change its properties and
that should be independent of having the definition assigned to a
variable otherwise it would be discarded as you say.

You can change a class’s properties, e.g. by adding methods etc. It’s
just that the name happens to be a read only property and there is some
additional magic which will set it on first constant assignment. I
don’t see how that collides with a “purist perspective”.

Did a bit of reading and at the end you can also create a class in
the following manner which allows you to define a name dynamically
with out using eval:

Object.const_set(“Bar”,Class.new)

See my posting in this thread from yesterday. :slight_smile:

Oh, and btw, that code does not really make sense that way because it
can be easily replaced by

Bar = Class.new

or even

class Bar
end

The approach with Object.const_set basically only makes sense if the
name is dynamic, too.

Everything can be done on a low level but usually we define artifacts
(classes, methods) to group functionality so we can access it more
conveniently and manage complexity.

This is due (from my opinion) to how the vm stores the classes as
constants in Object.

I find that wording slightly irritating: it sounds a bit as if you
assume the class is somehow in the constant. In Reality the constant
just references the class instance. There is no particular magic
involved other than the custom syntax with “class Name…end”.

I understand why but I think there should be a
more cleaner,abstract way to create Class definitions as they are
objects instead of the current Bare metal approach ( we get to see to
much of the internals ?)

I am not sure what you mean by “too much internals”. After all, I would
consider doing

Foo = Class.new do
def x;123;end
end

more bare metal than

class Foo
def x;123;end
end

Syntax with “class” certainly helps makes things a bit more abstract and
less “internal”. What would be the cleaner, more abstract way?

Cheers

robert

I understand how it works at the moment. Still if you are doing
metaprogramming and consider with a very purist perspective that
everything is an object then a Class definition is just an instance of
the Class Class and I should be able to change its properties and that
should be independent of having the definition assigned to a variable
otherwise it would be discarded as you say.

Did a bit of reading and at the end you can also create a class in the
following manner which allows you to define a name dynamically with out
using eval:

Object.const_set(“Bar”,Class.new)

This is due (from my opinion) to how the vm stores the classes as
constants in Object. I understand why but I think there should be a more
cleaner,abstract way to create Class definitions as they are objects
instead of the current Bare metal approach ( we get to see to much of
the internals ?)

On 26.03.2011 15:38, Vicente B. Campos wrote:

I understand how it works at the moment. Still if you are doing
metaprogramming and consider with a very purist perspective that
everything is an object then a Class definition is just an instance
of the Class Class

The definition is a definition, the result of executing it is an instance of
class Class.

I agree with you.

and I should be able to change its properties and
that should be independent of having the definition assigned to a
variable otherwise it would be discarded as you say.

You can change a class’s properties, e.g. by adding methods etc. It’s just that
the name happens to be a read only property and there is some additional magic
which will set it on first constant assignment. I don’t see how that collides
with a “purist perspective”.

I have not explained my self properly. Imagine we are talking about
making an instance of any other object e.g. a Car and the car has a name
and it allows you reference the car instance by it in the future.

Would you prefer the car name is defined by the variable that contains
it or by setting the name in the constructor?

hotwheels = Car.new

current_car = Car.new(“hotwheels”)

I don’t think anyone would understand directly that I have automatically
set a property inside my car with the variable name. It would be a bit
counterintuitive and different from how any other instance properties
work on this class and how they are usually set on any other type of
object of any library.

Considering the Class to be an object too by not allowing me set the
name at the .new and taking the name of the left hand side of the
equality sign in case it is a Constant ( otherwise it does not) it is
not acting very much like any other object.

Bar = Class.new

or even

class Bar
end

The approach with Object.const_set basically only makes sense if the name is
dynamic, too.

Yes sorry, I do want to have the name dynamic too ( I might be going
off-topic for the original post, sorry).

Everything can be done on a low level but usually we define artifacts (classes,
methods) to group functionality so we can access it more conveniently and manage
complexity.

This is due (from my opinion) to how the vm stores the classes as
constants in Object.

I find that wording slightly irritating: it sounds a bit as if you assume the
class is somehow in the constant. In Reality the constant just references the
class instance. There is no particular magic involved other than the custom
syntax with “class Name…end”.

Agreed, its just a reference. But if I want to have a dynamic name
without having to use eval I need to understand that the list of classes
defined are referred to as constants in the Object and I can do that
with

Object.const_set(“Bar”,Class.new)

I am just saying it would be nicer to do Class.new(“Bar”) would be much
more like any other object instantiation and less questioned about as it
would not be an exception to how the rest of the stuff works ( although
Class object is truly a bit of an exception and its one of those
marvelous things ruby allows us to tinker with ).

I understand why but I think there should be a
more cleaner,abstract way to create Class definitions as they are
objects instead of the current Bare metal approach ( we get to see to
much of the internals ?)

I am not sure what you mean by “too much internals”. After all, I would
consider doing

By “too much internals” I mean that I actually need to get to know that
the class Names are referenced in a list of constants in Object and that
I can do Object.const_set(“Bar”,Class.new) to create a class with a
dynamic name ( and not have to use eval) instead of Class.new(“Bar”).
( Sorry for going in circles)

Syntax with “class” certainly helps makes things a bit more abstract and less
“internal”. What would be the cleaner, more abstract way?

For a definition with a set name totally agree with you.

Cheers

Many thanks for the healthy discussion :slight_smile:

Cheers

Vicente

On Sat, Mar 26, 2011 at 1:16 PM, Vicente B. Campos [email protected]
wrote:

Considering the Class to be an object too by not allowing me set the name at the
.new and taking the name of the left hand side of the equality sign in case it is
a Constant ( otherwise it does not) it is not acting very much like any other
object.
Is there a way in Ruby to do this with objects generally (i.e. to
automatically set a name property upon assignment with =), not just
with Classes?

On 26.03.2011 19:16, Vicente B. Campos wrote:

perspective".

equality sign in case it is a Constant ( otherwise it does not) it is
not acting very much like any other object.

OK, now I get your point. Thanks! I think Matz just decides that doing

X = Class.new do
def foo; end
end

is less clean than

class X
def foo; end
end

and hence created the const magic because class definitions are so
common. If you want, you can still use the bar bones idiom though.

The approach with Object.const_set basically only makes sense if
the name is dynamic, too.

Yes sorry, I do want to have the name dynamic too ( I might be going
off-topic for the original post, sorry).

Then consider this: if the name is dynamic during definition it
certainly has to be dynamic during referencing as well. In that case
there is probably not much point in assigning the class to a constant.
Rather a Hash would be a much better place to keep all those classes
around. You could even do something like this:

irb(main):012:0> cl = Hash.new do |h,name|
irb(main):013:1* c = Class.new
irb(main):014:1> class<<c;self;end.send(:define_method, :name) { name }
irb(main):015:1> h[name]=c
irb(main):016:1> end
=> {}
irb(main):017:0> cl[“Foo”]
=> #Class:0x106c15bc
irb(main):018:0> cl[“Foo”]
=> #Class:0x106c15bc
irb(main):019:0> cl[“Foo”].name
=> “Foo”

or

irb(main):027:0> cl = {}
=> {}
irb(main):028:0> def cl.new_class(name, &b)
irb(main):029:1> c = Class.new(&b)
irb(main):030:1> class<<c;self;end.send(:define_method, :name) { name }
irb(main):031:1> self[name]=c
irb(main):032:1> end
=> nil
irb(main):033:0> cl.new_class “Foo” do
irb(main):034:1* def bar;123;end
irb(main):035:1> end
=> #Class:0x105a7364
irb(main):036:0> cl[“Foo”]
=> #Class:0x105a7364
irb(main):037:0> cl[“Foo”]
=> #Class:0x105a7364
irb(main):038:0> cl[“Foo”].name
=> “Foo”
irb(main):039:0> cl[“Foo”].new.bar
=> 123

Now the Hash defines a namespace where all your dynamic classes reside.
If you want to get rid of them you just need to clear the Hash. This
approach can be extended to define a specific DSL for your domain which
would make method definitions even simpler.

I am just saying it would be nicer to do Class.new(“Bar”) would be
much more like any other object instantiation and less questioned
about as it would not be an exception to how the rest of the stuff
works ( although Class object is truly a bit of an exception and its
one of those marvelous things ruby allows us to tinker with ).

Actually I haven’t seen the syntax “class Name … end” questioned in a
while. I believe this is such a fundamental and frequent idiom to
warrant a bit of syntactic sugar mixed with naming magic. :slight_smile:

Many thanks for the healthy discussion :slight_smile:

Ditto.

Kind regards

robert

On Mar 27, 2011, at 9:02 PM, Eric C. wrote:

Considering the Class to be an object too by not allowing me set the name at
the .new and taking the name of the left hand side of the equality sign in case it
is a Constant ( otherwise it does not) it is not acting very much like any other
object.

Is there a way in Ruby to do this with objects generally (i.e. to
automatically set a name property upon assignment with =), not just
with Classes?

I think this Constant “Magic” only works for classes as Robert has
indicated. At least I have not seen anything on google or my bookshelf
to do it.

I personally would not use it, its an exception of how the operator
works, and forces people to delve into how your object works which can
be considered as not very clean.

For the specific case of the Class and being such a high level
metaprogramming structure, love Ruby for it, I can understand why Matz
treated it as something special.

On Sun, Mar 27, 2011 at 10:38 PM, Vicente B. Campos
[email protected] wrote:

I think this Constant “Magic” only works for classes as Robert has indicated. At
least I have not seen anything on google or my
bookshelf to do it.

I personally would not use it, its an exception of how the operator works, and
forces people to delve into how your object works which
can be considered as not very clean.

But it allows some very nice things, like having ways of creating
classes, assign them to constants and have them work as a regularly
defined class very easily:

ruby-1.8.7-p334 :001 > TestClass = Struct.new :id
=> TestClass
ruby-1.8.7-p334 :004 > TestClass.name
=> “TestClass”

(Struct.new returns a class)

Jesus.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs