Two different results for Module.nesting

B

Brian Marick

Consider this:

module M1
module M2
class C
puts Module.nesting.inspect
end
end
end

It produces [M1::M2::C, M1::M2, M1], which I expected.

Now try this:

M1::M2::C.class_eval("Module.nesting")

It produces [M1::M2::C], which I did not expect. Why the difference?
Thanks.

VERSION: 1.8.1 and 1.6.8
 
S

Simon Strandgaard

Consider this: [snip]
It produces [M1::M2::C], which I did not expect. Why the difference?

Quoted form RI
"Returns the list of +Modules+ nested at the point of call."

The 'puts' occurs at 3 levels of nesting.
There is no modules surrounding 'p'..

Does that help ?

server> ruby -v
ruby 1.9.0 (2004-04-06) [i386-freebsd5.1]
server> ruby a.rb
[M1::M2::C, M1::M2, M1]
[M1::M2::C]
server> expand -t2 a.rb
module M1
module M2
class C
puts Module.nesting.inspect
end
end
end
p M1::M2::C.class_eval("Module.nesting")
server>
 
W

why the lucky stiff

Brian said:
Consider this:

module M1
module M2
class C
puts Module.nesting.inspect
end
end
end

It produces [M1::M2::C, M1::M2, M1], which I expected.

Now try this:

M1::M2::C.class_eval("Module.nesting")

It produces [M1::M2::C], which I did not expect. Why the difference?
Thanks.

It's returning the proper nesting. But as you haven't opened each of
the Modules individually to reach the C const, Module::nesting isn't
returning them each individual.

Let's illustrate:

module M1::M2
class C
puts Module.nesting.inspect
end
end
#=> [M1::M2::C, M1::M2]

_why
 
C

Chad Fowler

Brian said:
Consider this:

module M1
module M2
class C
puts Module.nesting.inspect
end
end
end

It produces [M1::M2::C, M1::M2, M1], which I expected.

Now try this:

M1::M2::C.class_eval("Module.nesting")

It produces [M1::M2::C], which I did not expect. Why the difference?
Thanks.

It's returning the proper nesting. But as you haven't opened each of
the Modules individually to reach the C const, Module::nesting isn't
returning them each individual.

Let's illustrate:

module M1::M2
class C
puts Module.nesting.inspect
end
end
#=> [M1::M2::C, M1::M2]

This strikes me as being a bit unintuitive, though I don't ever really
need it so I'm not too bothered. :)

It appears that this behavior is a remnant of the way Ruby is parsed
(or, more correctly, how it's eval(.c)uated). Brian, were you using
this for your automock thing?

I'm interested to hear what other uses people have found for this
method.

Chad
 
B

Brian Marick

Brian said:
Consider this:

module M1
module M2
class C
puts Module.nesting.inspect
end
end
end

It produces [M1::M2::C, M1::M2, M1], which I expected.

Now try this:

M1::M2::C.class_eval("Module.nesting")

It produces [M1::M2::C], which I did not expect. Why the difference?
Thanks.

It's returning the proper nesting. But as you haven't opened each of
the Modules individually to reach the C const, Module::nesting isn't
returning them each individual.

Let's illustrate:

module M1::M2
class C
puts Module.nesting.inspect
end
end
#=> [M1::M2::C, M1::M2]

This strikes me as being a bit unintuitive, though I don't ever really
need it so I'm not too bothered. :)

It seems unintuitive to me as well. I thought it would tell me about
the runtime module-nesting structure of the program, not about the
syntax by which I'm talking about that structure.

It appears that this behavior is a remnant of the way Ruby is parsed
(or, more correctly, how it's eval(.c)uated). Brian, were you using
this for your automock thing?

I came across it while fiddling around with automock.
<http://www.testing.com/cgi-bin/blog/2004/04/12#automock>
But I didn't have to use it.
 
J

Joel VanderWerf

Brian said:
Brian Marick wrote:

Consider this:

module M1
module M2
class C
puts Module.nesting.inspect
end
end
end

It produces [M1::M2::C, M1::M2, M1], which I expected.

Now try this:

M1::M2::C.class_eval("Module.nesting")

It produces [M1::M2::C], which I did not expect. Why the difference?
Thanks.


It's returning the proper nesting. But as you haven't opened each of
the Modules individually to reach the C const, Module::nesting isn't
returning them each individual.

Let's illustrate:

module M1::M2
class C
puts Module.nesting.inspect
end
end
#=> [M1::M2::C, M1::M2]

This strikes me as being a bit unintuitive, though I don't ever really
need it so I'm not too bothered. :)


It seems unintuitive to me as well. I thought it would tell me about the
runtime module-nesting structure of the program, not about the syntax by
which I'm talking about that structure.

I guess the value returned by #nesting has to be lexically determined
because ruby classes can be reopened. The following prints two different
nestings:

module M1
module M2
class C
puts Module.nesting.inspect
end
end
end

module M3
module M4
class C
puts Module.nesting.inspect
end
end
end

So there really is no "runtime" nesting structure. The nesting only
exists while the interpreter is evaluating code inside it.
 
C

Christoph

Joel VanderWerf wrote:
---
I guess the value returned by #nesting has to be lexically determined
because ruby classes can be reopened. The following prints two different
nestings:

module M1
module M2
class C
puts Module.nesting.inspect
end
end
end

module M3
module M4
class C
puts Module.nesting.inspect
end
end
end

So there really is no "runtime" nesting structure. The nesting only
exists while the interpreter is evaluating code inside it.

Here is another scriptlet demonstrating your point

---
module T
end

module Outer
module Inner
C = ::T
module C
$c = binding
end
end
end


class A
B = ::T
module B
$b = binding
end
end


p eval("Module.nesting",$c)
p eval("Module.nesting",$b)

---
[T, Outer::Inner, Outer]
[T, A]


/Christoph
 
G

George Marrows

Thanks for the very clear demonstration Christoph!

This issue of lexical code nesting vs 'intuitive' class/module nesting
isn't widely documented, but goes further than affecting just
Module.nesting. Its tentacles tickle the corner cases for class
variable and constant lookup, particularly when 'class X::Y' style
declarations are used.


Example for class variables:
http://www.rubygarden.org/ruby?ClassVariables


Example for constants:

E:\>type nesting.rb
class A
X = 1
class B
$b = self
puts "class A; class B"
puts X
end
end

class A::B
puts "Same class as previously? #{self == $b}"
puts "class A::B"
puts X
end

E:\>ruby -v nesting.rb
ruby 1.8.1 (2004-01-27) [i386-mswin32]
class A; class B
1
Same class as previously? true
class A::B
nesting.rb:13: uninitialized constant A::B::X (NameError)


-- George
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top