4

I can define an anonymous class within an anonymous module:

c = nil
m = Module.new do
  c = Class.new
end

m #=> #<Module:0x007fad3a055660>
c #=> #<Class:0x007fad3a0555e8>

Is the above equivalent to:

m = Module.new
c = Class.new

In other words: does the concept of "nesting" actually apply to anonymous modules?

Stefan
  • 109,145
  • 14
  • 143
  • 218

1 Answers1

2

It is not about being anonymous. Assigning a dynamically created class to a constant makes it named:

Foo = Class.new # => Foo
foo = Class.new # => #<Class:0x007fe5dd45d650>

Yet it still doesn't nest further:

module Bar
  Baz = Module.new do
    p Module.nesting # => [Bar]
  end
end

Or even about being dynamic for that matter:

module Quz
  eval 'module Qux; p Module.nesting; end' # => [Quz::Qux, Quz]
end

It's about scope gates.


As far as constants are concerned, there are only two scope gates - the keywords class and module.

Nesting is done purely syntactically. That is why you get the weird:

module Do
  X = 42
end

module Do
  module Re
    p Module.nesting # => [Do::Re, Do]
    p X              # => 42
  end
end

module Do::Mi
  p Module.nesting # => [Do::Mi]
  p X # => uninitialized constant
end

Do.module_eval   { p X } # => uninitialized constant
Do.instance_eval { p X } # => uninitialized constant

So if Ruby sees the keywords class or module, it nests the "current node" further. When the closing end is found, it goes up the tree. When a new constant is being defined, it places it in the current node.

ndnenkov
  • 35,425
  • 9
  • 72
  • 104
  • So `Module.nesting` is just a stack of modules used for constant lookup. Every `module` (or `class`) keyword pushes an arbitrary module onto the stack (popping it at `end`). And the top-most element functions as a prefix for new constants. – Stefan Dec 01 '16 at 07:24
  • Furthermore only _constants_ are stored and form an implicit hierarchy. The current nesting is transient and not stored anywhere – I can re-open the same module under different nestings. I would conclude: modules and classes cannot be nested, only constants can. Is that correct? – Stefan Dec 01 '16 at 07:34
  • @Stefan, yes. Named classes/modules get stored in the current nesting because they are constants (start with capital letter). – ndnenkov Dec 01 '16 at 07:36