From: Peter McLain Date: 2010-03-04T09:39:30+09:00 Subject: Re: Class vs Module in constant lookup On Mar 3, 2010, at 2:45 PM, Xavier Noria wrote: > On Wed, Mar 3, 2010 at 8:01 PM, Peter McLain > wrote: > >> Constant lookup behaves differently if there is a class versus a >> module in the name: >> >> XYZ = 10 >> >> module M >> end >> >> class C >> end >> >> p defined? M::XYZ # => nil >> p defined? C::XYZ # => "constant" >> >> Is this difference intended? If so, what is the rationale? > > I believe C::XYZ works because C is a subclass of Object. I think that will end up being part of the explanation, but I'm not yet convinced that it *should* be part of the explanation. p M.ancestors # => [M] p C.ancestors # => [C, Object, Kernel] The explanation for constant lookup in the Flanagan/Matz book, Section 7.9, starts off: "When a constant is referenced without any qualifying namespace..." and then goes on to explain constant lookup. Under those rules, I would expect both M and C to find the constant, and indeed, using unqualified names, they both do find it: XYZ = 10 module M p XYZ # => 10 p defined? XYZ # => "constant" end class C p XYZ # => 10 p defined? XYZ # => "constant" end But the original example was a fully qualified path: M::XYZ and C:XYZ. I didn't find any discussion of scoped constants. The draft ruby spec, however, leads me to believe that the MRI behavior is a bug. Section 11.4.3.2 of the spec discusses Scoped constant references. Under my reading of that section, and our test case, then (following the logic in that section): (a) the primary-expression is M, (b) M is a module (c 1) XYZ is the constant-identifier (c 2) XYZ is not one of the constants defined in M (c 3 i) There are no included modules in M (skip) (c 3 ii) N/A (c 3 iii) Goto step e of section 11.4.3.1 11.4.3.1 (e) M is not a class (e 1) Search Object for a binding for XYZ So we *should* find it in Object and MRI is incorrect to return nil. Did I miss something? -- Peter McLain peter.mclain@gemstone.com