tags:

views:

93

answers:

1

According to the documentation mod.const_get(sym) "Returns the value of the named constant in mod."

I also know that const_get by default may look up the inheritance chain of the receiver. So the following works:

class A; HELLO = :hello; end
class B < A; end
B.const_get(:HELLO) #=> :hello

I also know that classes in Ruby subclass Object, so that you can use const_get to look up 'global' constants even though the receiver is a normal class:

class C; end
C.const_get(:Array) #=> Array

However, and this is where i'm confused -- modules do not subclass Object. So why can I still look up 'global' constants from a module using const_get? Why does the following work?

module M; end
M.const_get(:Array) #=> Array

If the documentation is correct - const_get simply looks up the constant defined under the receiver or its superclasses. But in the code immediately above, Object is not a superclass of M, so why is it possible to look up Array ?

Thanks

+2  A: 

You are correct to be confused... The doc doesn't state that Ruby makes a special case for lookup of constants in Modules. If the constant has not been found in the normal hierarchy, Ruby restarts the lookup from Object, as can be found in the source.

Constant lookup by itself can be bit confusing. Take the following example:

module M
  Foo = :bar
  module N
    # Accessing Foo here is fine:
    p Foo # => bar
  end
end
module M::N
  # Accessing Foo here isn't
  p Foo  # => uninitialized constant M::N::Foo
end
p M::N.const_get :Foo  # => uninitialized constant M::N::Foo

In both places, though, accessing Object level constants like Array is fine (thank god!). What's going on is that Ruby maintains a list of "opened Module definitions". If a constant has an explicit scope, say LookHereOnly::Foo, then only LookHereOnly and its included modules will be searched. If no scope is specified (like Foo in the example above), Ruby will look through the opened module definitions to find the constant Foo: M::N, then M and finally Object. The topmost opened module definition is always Object.

So M::N.const_get :Foo is equivalent to accessing Foo when the opened classes are only M::N and Object, like in the last part of my example.

I hope I got this right, coz I'm still confused by constant lookups myself :-)

I'll try to improve the rdoc for const_get shortly.

Marc-André Lafortune
Any idea why it does that? In what cases would that be useful?
sepp2k
@sepp2k: not sure if it is _useful_, but I tried explaining what I think is the logic behind it.
Marc-André Lafortune