Nesting and constants

module TT_Test

  module Foo
    CHEESE = 'I am Foo!'
    module Bar
      def self.prod
        puts CHEESE
      end
      def self.q
      p Module.nesting
    end
    end # Bar
    def self.q
      p Module.nesting
    end
  end # Foo

  module Foo::Biz
    def self.prod
      puts CHEESE
    end
    def self.q
      p Module.nesting
    end
  end # Foo

end # TT_Test

TT_Test::Foo.q
# => [TT_Test::Foo, TT_Test]

TT_Test::Foo::Bar.q
# => [TT_Test::Foo::Bar, TT_Test::Foo, TT_Test]

TT_Test::Foo::Bar.q
# => [TT_Test::Foo::Bar, TT_Test]

TT_Test::Foo.constants
# => ["Biz", "Bar", "CHEESE"]

My question is: Why is the constant scope different between Bar and Biz
- despite that they both exist under TT_Test::Foo ? I mean, if TT_Test
got a constant named "Foo::Biz" I would have understood the constant
lookup.

···

--
Posted via http://www.ruby-forum.com/.

module TT_Test

  module Foo
    CHEESE = 'I am Foo!'
    module Bar
      def self.prod
        puts CHEESE
      end
      def self.q
      p Module.nesting
    end
    end # Bar
    def self.q
      p Module.nesting
    end
  end # Foo

  module Foo::Biz
    def self.prod
      puts CHEESE
    end
    def self.q
      p Module.nesting
    end
  end # Foo

end # TT_Test

TT_Test::Foo.q
# => [TT_Test::Foo, TT_Test]

TT_Test::Foo::Bar.q
# => [TT_Test::Foo::Bar, TT_Test::Foo, TT_Test]

TT_Test::Foo::Bar.q
# => [TT_Test::Foo::Bar, TT_Test]

TT_Test::Foo.constants
# => ["Biz", "Bar", "CHEESE"]

My question is: Why is the constant scope different between Bar and Biz
- despite that they both exist under TT_Test::Foo ? I mean, if TT_Test
got a constant named "Foo::Biz" I would have understood the constant
lookup.

The module keyword pushes to the nesting the module it has opened (either
just created or reopened).

Therefore, in

    module M
      module N
        p Module.nesting # => [M::N, M]
      end
    end

because first we open M, and then in a nested call we open M::N. But on the
other hand

    module M::N
      p Module.nesting # => [M::N]
    end

opens M::N and that's it. Nesting gets just that one module object pushed.

Note that what we push are module objects, not constants:

    module M
    end

    N = M

    module N
      p Module.nesting # => [M]
    end

In the example above, N evaluates to the module object stored in the
constant M, that's the module object being reopened and therefore pushed to
the nesting.

···

On Tue, Aug 7, 2012 at 4:02 PM, Thomas Thomassen <lists@ruby-forum.com>wrote:

Hi,

Module.nesting lists all modules that *lexically* surround the method
call. So it only takes into account the modules that are actually
present in the form of

module ...
  module ...
    ...
  end
end

If a parent module is only mentioned in the name, it's ignored.

···

--
Posted via http://www.ruby-forum.com/.

This has just recently been reported to Ruby's issue tracker:
http://bugs.ruby-lang.org/issues/6810

-- Matma Rex

Bartosz Dziewoński wrote in post #1071556:

This has just recently been reported to Ruby's issue tracker:
Feature #6810: `module A::B; end` is not equivalent to `module A; module B; end; end` with respect to constant lookup (scope) - Ruby master - Ruby Issue Tracking System

-- Matma Rex

The comments there reflects what Matz mentions here:

But I still don't understand why this is considered expected behaviour.
All I can find is technical explanation to what happens - but not the
reason and logic for it. From my point of view it's counter-intuitive
and I cannot see a use-case for it.

···

--
Posted via http://www.ruby-forum.com/\.

The comments there reflects what Matz mentions here:

Hot XXX Images, Best Porn Pics and Free Sex Photos on www.pornfalcon.com

But I still don't understand why this is considered expected behaviour.

Well, it is expected behavior because that's the way Ruby works.

A given module can be stored in a hundred constants in dozens of
differently nested constant paths. Constants are largely irrelevant to
Ruby, Ruby semantics are defined around module and class objects.

So, the rule is that whatever module object is opened by the module
keyword, that's what gets pushed to the nesting. It is simple, and it works
in all cases. It does not matter the constant path used to reach the module
object. Given (untested code):

    module M
      N = Module.new
    end

    module A
      module B
        C = M::N
      end
    end

    module M::N
      # (1)
    end

    module A::b::C
      # (2)
    end

    X = M::N
    module X
      # (3)
    end

the nesting in (1), (2), and (3) is the same (M::N). The fact that we got
the M::N module via X or A::b::C is irrelevant. And the fact that we reach
it via M::N is equally irrelevant by the same principle. *Constants do not
matter*, Ruby only cares about the module objects they yield.

In my view all is round and follows those basic axioms, but of course the
only one who can ensure which is the rationale is Matz himself.

···

On Tue, Aug 7, 2012 at 6:06 PM, Thomas Thomassen <lists@ruby-forum.com>wrote: