# Constant name resolution and module\_eval

**URL:** <https://www.ruby-forum.com/t/constant-name-resolution-and-module-eval/120370>\
**Category:** Ruby\
**Created:** [November 16, 2007, 9:51am UTC](https://www.ruby-forum.com/t/constant-name-resolution-and-module-eval/120370 "2007-11-16T09:51:03Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![fxn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/77aa72/32.png) [@fxn](https://www.ruby-forum.com/u/fxn)\
**Post date:** [November 16, 2007, 9:51am UTC](https://www.ruby-forum.com/t/constant-name-resolution-and-module-eval/120370/1 "2007-11-16T09:51:03Z")

</div>

I’m trying to understand well the rules for constant name resolution.  
By now what I have is:

(1) A constant is first looked up in the current module,  
then recursively in its mixins (ancestors). Then go up  
to the parent, and iterate up to the mixins of Object.

(2) When you resolve a relative path Foo::Bar first you  
resolve the constant Foo using the rule above. If found,  
you look for Bar in Foo. There’s no backtracking if that  
choice for Foo fails.

If that’s right, I need yet to refine what’s the “current module”.  
From my trials looks like the current module is determined by “module/  
class” explicit keyword nesting, and module\_eval does not change it:

C = “Object”

module M  
C = “M”  
end

M.module\_eval do  
def self.const; C end  
D = 1  
end

puts M.const  
puts M:😃 # -\> NameError

But surprisingly module\_eval defines M.const, and does _not_ define  
M::D. I know module\_eval sees the surrounding scope and that allows  
some idioms a regular module reopening does not, but I need yet to put  
the pieces together for constants.

Is that there are two kinds of "current module"s, one for constant  
lookup, and another one for method definitions, which happen to match  
when you use the “module/class” keyword nesting? My trials suggest  
that’s the case but I’d like someone with a better understanding of  
Ruby internals to confirm it and perhaps define more clearly those two  
“current” modules at any given point of the program.

– fxn

---

<div class="post-metadata">

**Author:** ![fxn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/77aa72/32.png) [@fxn](https://www.ruby-forum.com/u/fxn)\
**Post date:** [November 16, 2007, 11:16am UTC](https://www.ruby-forum.com/t/constant-name-resolution-and-module-eval/120370/2 "2007-11-16T11:16:44Z")

</div>

On Nov 16, 2007 9:49 AM, Xavier N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> choice for Foo fails.
> 
> M.module\_eval do  
> def self.const; C end  
> D = 1  
> end
> 
> puts M.const  
> puts D → 1  
> it seems that constants behave as _declared_ locals in closures.  
> puts M:😃 # → NameError  
> see this for contrast, it is not module\_eval that makes the difference  
> but the closure/block semantics  
> M.module\_eval \<\<-EOS  
> def self.const; C end  
> D = 1  
> EOS

puts M.const  
puts M:😃 # → 1

> But surprisingly module\_eval defines M.const, and does _not_ define  
> M::D. I know module\_eval sees the surrounding scope and that allows  
> some idioms a regular module reopening does not, but I need yet to put  
> the pieces together for constants.  
> No it is not module\_eval that sees the surrounding scope it is the  
> closure, as you can verify with the string  
> form of module\_eval.  
> I did not know that behavior for constants either, very interesting.

HTH  
Robert

---

<div class="post-metadata">

**Author:** ![fxn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/77aa72/32.png) [@fxn](https://www.ruby-forum.com/u/fxn)\
**Post date:** [November 16, 2007, 11:26am UTC](https://www.ruby-forum.com/t/constant-name-resolution-and-module-eval/120370/3 "2007-11-16T11:26:06Z")

</div>

On Nov 16, 2007, at 11:14 AM, Robert D. wrote:

> > some idioms a regular module reopening does not, but I need yet to  
> > put  
> > the pieces together for constants.  
> > No it is not module\_eval that sees the surrounding scope it is the  
> > closure, as you can verify with the string  
> > form of module\_eval.  
> > I did not know that behavior for constants either, very interesting.

Good point!

And with that alternative M.const gives “M” instead of “Object” as  
well. Very interesting.

– fxn
