Two different results for Module.nesting

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

···

Brian Marick
Consulting, training, and contracting
Mostly on agile methods with a testing slant
www.testing.com, www.testing.com/cgi-bin/blog

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 ?

ruby -v
ruby 1.9.0 (2004-04-06) [i386-freebsd5.1]
ruby a.rb
[M1::M2::C, M1::M2, M1]
[M1::M2::C]
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”)

···

On Tue, 13 Apr 2004 07:15:58 +0900, Brian Marick wrote:


Simon Strandgaard

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]

_why

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

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

···

On 12/4/2004, at 9:26 PM, why the lucky stiff wrote:

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]

Hi –

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. :slight_smile:

It’s similar to the way constant definitions are scoped:

irb(main):001:0> module A; X=1; module B; p X; end; end
1
=> nil
irb(main):002:0> module A::B; p X; end
NameError: uninitialized constant A::b::X
from (irb):2
irb(main):003:0> module A::B; p A::X; end
1

i.e., if you say “module A::B” it’s different from entering one level
at a time. (I don’t think this syntax existed in pre-1.8, but I guess
the idea as applied to Module.nesting was similar.)

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

None. In fact, until today I didn’t know (or had forgotten) that it
existed.

David

···

On Tue, 13 Apr 2004, Chad Fowler wrote:

On 12/4/2004, at 9:26 PM, why the lucky stiff wrote:


David A. Black
dblack@wobblini.net

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. :slight_smile:

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.

···

On Apr 12, 2004, at 9:32 PM, Chad Fowler wrote:

On 12/4/2004, at 9:26 PM, why the lucky stiff wrote:


Brian Marick
Consulting, training, and contracting
Mostly on agile methods with a testing slant
www.testing.com, www.testing.com/cgi-bin/blog

Brian Marick wrote:

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. :slight_smile:

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.

···

On Apr 12, 2004, at 9:32 PM, Chad Fowler wrote:

On 12/4/2004, at 9:26 PM, why the lucky stiff wrote:

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

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