Hi --

On Sun, 5 Mar 2006, Dominik Bathon wrote:

> But actually it's even more complicated (continuing your code):
>
> $obj=obj
> class Object
> 	class << $obj
> 		def i
> 			puts X
> 		end
> 	end
> end
>
> obj.i #=>top-level
>
> This is because the constant lookup first checks in all the outer lexical 
> scopes if the constant is directly defined in one of the classes and then 
> does a full const_get on the innermost class. So in this case, the following 
> happens:
>
> 1. Does #<Class:#<D:0xb7f3bda0>> (without ancestors) have a constant X => no
> 2. Does Object (without ancestors) have a constant X => yes => constant found
>
> If step 2 wouldn't have found the constant then ruby would have checked the 
> ancestors of #<Class:#<D:0xb7f3bda0>> for the constant:
>
> class D
> 	Y = "D::Y"
> end
>
> class Object
> 	class << $obj
> 		def j
> 			puts Y
> 		end
> 	end
> end
>
> obj.j #=>D::Y
>
> Here the following happens:
>
> 1. Does #<Class:#<D:0xb7f3bda0>> (without ancestors) have a constant Y => no
> 2. Does Object (without ancestors) have a constant Y => no
> 3. Does #<Class:#<D:0xb7f3bda0>> (including ancestors) have a constant Y => 
> yes => constant found

But Object is always an ancestor, so you don't need step 2.  Also,
step 2 (lookup in Object) doesn't really happen second; for example,
if you put yourself in D context, the lookup will hit D::X before it
hits Object::X:

$obj=obj
class Object
   class D
     class << $obj
       def k
         puts X
       end
     end
   end
end

obj.k  # class-level

So the resolution path is:

   #<Class:#<D...>>
     D                 # X found here
      Object           # X exists here but not reached

As I understand it, some of this is determined quasi-statically...
though not the singleton class parts, since those can't be determined
at all until runtime.


David

-- 
David A. Black (dblack / wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black