[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

constant name resolution and module_eval

Xavier Noria

11/16/2007 8:50:00 AM

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::D # -> 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


2 Answers

Robert Dober

11/16/2007 10:15:00 AM

0

On Nov 16, 2007 9:49 AM, Xavier Noria <fxn@hashref.com> wrote:
> 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 D -> 1
it seems that constants behave as *declared* locals in closures.
> puts M::D # -> 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::D # -> 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


--
what do I think about Ruby?
http://ruby-smalltalk.blo...

Xavier Noria

11/16/2007 10:24:00 AM

0

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

> M.module_eval <<-EOS
> def self.const; C end
> D = 1
> EOS
>
> puts M.const
> puts M::D # -> 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.


Good point!

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

-- fxn