-->

Can anonymous modules and class be nested in Ruby?

2019-05-09 11:39发布

问题:

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?

回答1:

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.