Issue #6810 has been updated by pedz (Perry Smith).


I agree with Alexey... I'm surprised.

His third example shows that the lookup of N is done at run time and starts from the inner scope of B, if no match, search A, if no match search globals. ... At least, that is how it appears to me.

But the fourth example does not mimic this search pattern.  It is as if A::B is not nested under A but is a unique constant.

Xavier's first reply https://bugs.ruby-lang.org/issues/6810#note-1 shows this as well.

This explains some "weirdness" (a.k.a. "surprise") I've experienced in the past and I view it as a bug.  Indeed, I view both outputs in Xavier's first reply as wrong.  They both should be [B,A].  A::B is just a shorthand to gain access to the constant B syntactically nested inside of module A.

At least, that is what I thought it was doing all this time.

Looking at the Dave Thomas' Ruby 1.9 book for why I think this way I see a lot of reasons why.  And I wonder if this doesn't relate to some of the class variable "leakage" he details around page 308 in Part III, Chapter 22, section "Scope of Constants and Variables"

Now... it may be that it won't change.  So I think Xavier's presentation needs to be part of Ruby 101 rather than an obscure relatively unknown topic.

----------------------------------------
Bug #6810: `module A::B; end` is not equivalent to `module A; module B; end; end` with respect to constant lookup (scope)
https://bugs.ruby-lang.org/issues/6810#change-28534

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee: 
Category: core
Target version: 
ruby -v: ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin10.8.0]


=begin
Is this the expected behavior?  To me it is rather surprising:

 N = 0

 module A
   module B
     def self.f; N; end
   end
   N = 1
 end

 A::B.f # => 1

but

 N = 0

 module A; end

 module A::B
   def self.f; N; end
 end

 module A
   N = 1
 end

 A::B.f # => 0

Even more striking:

 module A
   module B
     def self.f; N; end
   end
 end

 N = 0

 A::B.f # => 0

 A::N = 1

 puts A::B.f # => 1

 A::B::N = 2

 A::B.f # => 2

but

 module A; end

 module A::B
   def self.f; N; end
 end

 N = 0

 A::B.f # => 0

 A::N = 1

 A::B.f # => 0

 A::B::N = 2

 A::B.f # => 2


=end


-- 
http://bugs.ruby-lang.org/