Module.nesting -> Kernel#nesting

T

Trans

I'm trying to write a little method called Module#modspace, which will
return the module/class a module/class is defined in. I.e.

Module X
Module Y
Module Z
end
end
end

X::Y::Z.modspace #=> X::Y


So I thought, Module.nesting would help do the trick. But I discovered
the Module.nesting returns the nesting according where it is called in
the code, nothing more. It is like __LINE__ or __FILE__ in this
respect. So it seems to me that it would be more appropriate to define
#nesting in Kernel, not as a class method of Module.

BTW, any help writing Module#modspace appreciated.

T.
 
D

Dale Martenson

---- Original message from Trans on 8/16/2005 2:36 PM:
I'm trying to write a little method called Module#modspace, which will
return the module/class a module/class is defined in. I.e.

Module X
Module Y
Module Z
end
end
end

X::Y::Z.modspace #=> X::Y


So I thought, Module.nesting would help do the trick. But I discovered
the Module.nesting returns the nesting according where it is called in
the code, nothing more. It is like __LINE__ or __FILE__ in this
respect. So it seems to me that it would be more appropriate to define
#nesting in Kernel, not as a class method of Module.
This is mostlikely not the best way to do it, but here is a way to get
at the information.

class Module
def lineage
eval self.ancestors.to_s.sub( /::[^:]$/, "" )
end
def modspace
lineage
end
end

module X
module Y
module Z
end
end
end

a = X::Y::Z

p a.modspace
p a.modspace.class
 
J

Joel VanderWerf

Dale said:
class Module
def lineage
eval self.ancestors.to_s.sub( /::[^:]$/, "" )

You can use name.sub(...) instead of self.ancestors.to_s.sub(...), but
it's not much better.
 
D

Dale Martenson

---- Original message from Joel VanderWerf on 8/16/2005 5:04 PM:
Dale Martenson wrote:

class Module
def lineage
eval self.ancestors.to_s.sub( /::[^:]$/, "" )

You can use name.sub(...) instead of self.ancestors.to_s.sub(...), but
it's not much better.
Actually, it is a lot better since you avoid cases where there are
additional includes. Module#ancestors
returns an array which causes problems with my original suggestion.

Example:

module X
include Math
module Y
include Comparable
module Z
include Enumerable
end
end
end

Thanks, Joel for your suggestion. For some reason, Module#name just
didn't come to mind.
 
T

Trans

Nice use of #eval. That's what I was missing. ( I usually try to avoid
#eval, but in this case it makes it much easier).

Thanks,
T.

P.S. Anyone on why #nesting isn't in Kernel?
 
P

Pit Capitain

Trans said:
P.S. Anyone on why #nesting isn't in Kernel?

Maybe because the only thing you can nest are modules, and the result is
a list of modules? IMO, it has nothing to do with general objects.

Regards,
Pit
 
T

Trans

Pit said:
Maybe because the only thing you can nest are modules, and the result is
a list of modules? IMO, it has nothing to do with general objects.

Actually that's my point. What you say is the common general thought,
it's exactly what I had thought, but it's isn't true. #nesting actually
has nothing to do with it's reciever 'class Module'. And has more do
with the object, namely, the nesting from _that place in the object_,
well, at least as much as __LINE__ and __FILE__ do. By analogy, we
don't use 'File.__LINE__'. Do you see what I'm getting at?

Kernel is not so much a mixin of Object, as it is a omni-accessible
toolchest for the Ruby coder.

T.
 
P

Pit Capitain

Trans said:
Actually that's my point. What you say is the common general thought,
it's exactly what I had thought, but it's isn't true. #nesting actually
has nothing to do with it's reciever 'class Module'.

Seems I can't express my thoughts very well. I know that Module.nesting
isn't an instance method of Module and that you can't ask an instance of
Module for its nesting.

What I wanted to say is that the value of Module.nesting depends only on
the nesting of module definitions. It only matters in which (lexical)
module context it is called. It has nothing to do with other objects. If
you'd remove the class Module from Ruby, a nesting method wouldn't make
sense anymore.
And has more do
with the object, namely, the nesting from _that place in the object_,
well, at least as much as __LINE__ and __FILE__ do. By analogy, we
don't use 'File.__LINE__'. Do you see what I'm getting at?

Yes, but you could remove the class File from Ruby and it would still
make sense to get the name of the current source file. The current
source file is a property of the compile time environment and has
nothing to do with any Ruby language constructs. From this point of view
it wouldn't make sense to associate __FILE__ with the Ruby class File.
Kernel is not so much a mixin of Object, as it is a omni-accessible
toolchest for the Ruby coder.

But __FILE__ is a token recognized by the parser. It is neither a
constant nor a method of any module, including Kernel.

As always just my 2 cents.

Regards,
Pit
 
T

Trans

But __FILE__ is a token recognized by the parser. It is neither a
constant nor a method of any module, including Kernel.

True. But if you were to try to define it yourself it woul be a Kernel
module.

Anyway, I've come back to this old thread b/c I realize now, why
exactly this would be more approriate as a Kernel method and not a
Module method: the definition requires a "Binding.of_caller" in order
to work --ie. if one were to try to do it in ruby themselves. So
underthehood it must be doing the same. Since Binding.of_caller is
considered "not good" (do I understand correctly that matz has
declined this functionality for Ruby?) then this method goes against
that grain.

How did I realize this? I was trying to write an Ruby interpolate
method as a String module function. And for the same reason it was not
possible --I had to put it in Kernel.

T.
 
T

Trans

Trans said:
True. But if you were to try to define it yourself it woul be a Kernel
module.

Anyway, I've come back to this old thread b/c I realize now, why
exactly this would be more approriate as a Kernel method and not a
Module method: the definition requires a "Binding.of_caller" in order
to work --ie. if one were to try to do it in ruby themselves. So
underthehood it must be doing the same. Since Binding.of_caller is
considered "not good" (do I understand correctly that matz has
declined this functionality for Ruby?) then this method goes against
that grain.

How did I realize this? I was trying to write an Ruby interpolate
method as a String module function. And for the same reason it was not
possible --I had to put it in Kernel.

Well, I'll correct myself. Techincally, you still need
Binding.of_caller using Kernel. It's just that Kernel's modus operandi
is functionality unversally present, so it seems like the right place.

T.
 
S

Sean O'Halpin

This does the same job without using eval:

class Module
def lineage
name.split(/::/)[0..-2].inject(self) do |mod, modname|
mod.const_get(modname)
end
end
def modspace
lineage
end
end

module X
include Math
module Y
include Comparable
module Z
include Enumerable
end
end
end

x =3D X
y =3D X::Y
z =3D X::Y::Z

p x.modspace
p x.modspace.class

p y.modspace
p y.modspace.class

p z.modspace
p z.modspace.class

__END__
---------- Ruby ----------
X
Module
X
Module
X::Y
Module

Output completed (0 sec consumed) - Normal Termination

Not that I think eval is evil. I find it very handy.

I'm not sure what it means for X's modspace (aka 'lineage') to be X but tha=
t's
how the original worked. Perhaps it should be Module?
You can get this behaviour by changing inject(self) to inject(Module).

I'm curious - what would you do with this?

Regards

Sean
 

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

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top