Module#constants

According to my trials nor Module#constants neither Module#const_get work with constants defined in enclosing modules:

   module M
     C = 1
     module N
       C # -> 1
     end
   end

   M::N.constants # -> []
   M::N.const_get("C") # -> NameError

Looks as if they only took into account ancestors.

But the Pickaxe says that Module#constants:

"Returns an array of the names of the constants accessible in mod. This includes the names of constants in any included modules (example at start of section)."

Does "This includes" mean "These are"? Is there a way to obtain "M::C" as qualified name of a constant visible by N?

-- fxn

I gues that C is somehow in scope, but there are other examples that puzzle me:

   module M
     C = 1
   end

   module PutSomethingInBetweenJustInCase
   end

   module M
     module N
       puts C # -> 1
     end
   end

Why is M::C in scope there?

-- fxn

···

On Nov 14, 2007, at 1:27 AM, Xavier Noria wrote:

According to my trials nor Module#constants neither Module#const_get work with constants defined in enclosing modules:

module M
   C = 1
   module N
     C # -> 1
   end
end

M::N.constants # ->
M::N.const_get("C") # -> NameError

Looks as if they only took into account ancestors.

for the same reason that File and Object are. imagine if C were not, then we would have to write

   ::File.open path

whenever opening a File.

the scope crawls up the nesting.

a @ http://codeforpeople.com/

···

On Nov 14, 2007, at 5:44 AM, Xavier Noria wrote:

Why is M::C in scope there?

--
it is not enough to be compassionate. you must act.
h.h. the 14th dalai lama

Thank you! I had once that hypothesis but this example broke it:

   module M
     C = 1
     module N
     end
   end

   M::N.module_eval do
     File # -> OK
     C # -> NameError
   end

File is seen but C is not. So I think there's something more into it. The best conjecture I have by now is that you need to have the enclosing module syntactically there with the nested "module/class"s.

However, I have seen that even if there something syntactic the name of the constant is not used, I mean this works:

   module M
     C = 1
     module N
     end
   end

   X = M
   module X
     module N
       C
     end
   end

That makes some sense because if X is already a module that module is reponed, fine, but all the examples together give kind of a mix of runtime and syntatic things to take into account.

I don't yet understand the complete rule.

-- fxn

···

On Nov 14, 2007, at 6:36 PM, ara.t.howard wrote:

On Nov 14, 2007, at 5:44 AM, Xavier Noria wrote:

Why is M::C in scope there?

for the same reason that File and Object are. imagine if C were not, then we would have to write

::File.open path

whenever opening a File.

the scope crawls up the nesting.

Nah, that didn't add information. When the code is interpreted and we arrive to "module X" the X constant is looked up and has a module as value, which happens to be the same module object that is stored under M. So that example is no different from plain

   module M
     module N
       C
     end
   end

This test brings some light in what I think I don't understand:

   module M
     C = 1
     module N
     end
   end

   class Module
     def const_missing(c)
       puts self
     end
   end

   M::N.module_eval do
     C
     puts self
   end

Gives:

   Object
   M::N

So I think I am narrowing this to how scope works. I know module_eval sees stuff from the surrounding scope, but I think I have a misunderstanding between "scope" and "evaluating the block in the context of M::N".

There's some module that's taken as a starting point to crawl up in the namespace for constant resolution (Object), and there's a different module to which method definitions _but not constant definitions_ apply (the remark about constants is not proven in the example).

Can anyone define those "two" modules better?

-- fxn

···

On Nov 14, 2007, at 9:41 PM, Xavier Noria wrote:

However, I have seen that even if there something syntactic the name of the constant is not used, I mean this works:

module M
   C = 1
   module N
   end
end

X = M
module X
   module N
     C
   end
end