Obtaining a reference to an enclosing class of a nested class

J

John Lam

Here is a nested class definition:

class A
class B
end
end

Now, if I have a reference to class B from somewhere:

def get_reference
A::B
end

reference_b = get_reference

How can I get a reference to the enclosing class A?

I can't do this by symbol lookup since class A (and B for that matter)
are anonymous. Am I going to have to explicitly create a
back-reference to the enclosing class at the time that I create class
B?

Thanks
-John
http://www.iunknown.com
 
R

Rick DeNatale

Here is a nested class definition:

class A
class B
end
end

Now, if I have a reference to class B from somewhere:

def get_reference
A::B
end

reference_b = get_reference

How can I get a reference to the enclosing class A?

Well in this case, since we know(?) it's a Class or Module:

reference_b.name => "A::B"

So you can get A's name by string manipulation.
I can't do this by symbol lookup since class A (and B for that matter)
are anonymous. Am I going to have to explicitly create a
back-reference to the enclosing class at the time that I create class
B?

Do you really mean that they are anonymous, or that you don't directly
know the name?
 
J

John Lam

Yep - they're anonymous. I'm rewriting how RubyCLR deals with shadow
class references to generic types, and I've made a design decision
that shadow classes don't really need names. The anonymous class
objects are bound to constants only when necessary (I could avoid this
too, but I haven't measured how expensive calls to const_missing vs. a
hit on a constant are - I suspect it's faster to have constants
pre-created).

I used to mangle class names so that:

List<String>

becomes

List_generic_System_String

but this becomes insanely complex when you consider all of the corner
cases involving generic types and nested generic types. I cut a ton of
complexity out of the code by simply not naming the classes anymore.
That works until this case.

Right now I'm explicitly adding a back-reference to the anonymous
class objects that I create which works just fine. I was just
wondering if there was something in the Ruby type system that would
let me do this already so that I'm not wasting memory duplicating
something that I can already do.

I'm fairly certain that I can't do this, but I thought I'd run it past
folks with more experience than me.

Cheers,
-John
http://www.iunknown.com
 
J

Joel VanderWerf

John said:
Here is a nested class definition:

class A
class B
end
end

Now, if I have a reference to class B from somewhere:

def get_reference
A::B
end

reference_b = get_reference

How can I get a reference to the enclosing class A?

I can't do this by symbol lookup since class A (and B for that matter)
are anonymous. Am I going to have to explicitly create a
back-reference to the enclosing class at the time that I create class
B?

Thanks
-John
http://www.iunknown.com

class A
class B
@nesting = Module.nesting
class << self; attr_reader :nesting; end
end
end

p A::B.nesting # ==> [A::B, A]

However, you say the classes are anonymous. How are you getting B under
the scope of A in that case?
 
J

Joel VanderWerf

John said:
Here is a nested class definition:

class A
class B
end
end

Now, if I have a reference to class B from somewhere:

def get_reference
A::B
end

reference_b = get_reference

How can I get a reference to the enclosing class A?

I can't do this by symbol lookup since class A (and B for that matter)
are anonymous. Am I going to have to explicitly create a
back-reference to the enclosing class at the time that I create class
B?

Thanks
-John
http://www.iunknown.com

class A
class B
@nesting = Module.nesting
class << self; attr_reader :nesting; end
end
end

p A::B.nesting # ==> [A::B, A]

However, you say the classes are anonymous. How are you getting B under
the scope of A in that case?
 
L

Logan Capaldo

However, you say the classes are anonymous. How are you getting B
under
the scope of A in that case?

mod1 = Module.new
mod2 = nil
mod1.module_eval{ mod2 = Module.new }

 
J

Joel VanderWerf

Logan said:
mod1 = Module.new
mod2 = nil
mod1.module_eval{ mod2 = Module.new }

I don't think mod2 is nested in mod1, in any sense. There's no reason
for ruby to keep track of the modules that are created during the
execution of the block that accompanies the mod1.module_eval call and to
associate them with mod1. The only reason B is associated with A in

module A
module B; end
end

is that they are lexically related. (More precisely the constant "B" is
in the namespace belonging to the class A.)

Maybe someone else has a more definitive answer?
 
L

Logan Capaldo

I don't think mod2 is nested in mod1, in any sense. There's no
reason for ruby to keep track of the modules that are created
during the execution of the block that accompanies the
mod1.module_eval call and to associate them with mod1. The only
reason B is associated with A in

module A
module B; end
end

is that they are lexically related. (More precisely the constant
"B" is in the namespace belonging to the class A.)

Maybe someone else has a more definitive answer?

VALUE rb_define_module_under(VALUE outer, const char *name)

You could use this to define a named module under an anonymous module.
 
R

Rick DeNatale

But module nesting is namespace nesting, so what does it mean to put a
nameless object in a namespace?

I don't think mod2 is nested in mod1, in any sense. There's no
reason for ruby to keep track of the modules that are created
during the execution of the block that accompanies the
mod1.module_eval call and to associate them with mod1. The only
reason B is associated with A in

module A
module B; end
end

is that they are lexically related. (More precisely the constant
"B" is in the namespace belonging to the class A.)

Maybe someone else has a more definitive answer?

VALUE rb_define_module_under(VALUE outer, const char *name)

You could use this to define a named module under an anonymous module.


--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/

Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/
 
J

Joel VanderWerf

Rick said:
But module nesting is namespace nesting, so what does it mean to put a
nameless object in a namespace?

It's the other way around: a named object in an unnamed namespace, using
rb_define_module_under.
 
R

Rick DeNatale

It's the other way around: a named object in an unnamed namespace, using
rb_define_module_under.

Except that the OP said that BOTH were anonymous. Pasting from the
original post:
 
L

Logan Capaldo

Except that the OP said that BOTH were anonymous. Pasting from the
original post:
I was just pointing out ways something like that could possibly come
to occur.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top