# Problem trying to get a constant with correct scope

**URL:** <https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434>\
**Category:** ruby-talk\
**Created:** [30 November 2009 21:15 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434 "2009-11-30T21:15:35Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alexandre\_Mutel](https://avatars.discourse-cdn.com/v4/letter/a/db5fbb/32.png) [@Alexandre\_Mutel](https://rubytalk.org/u/Alexandre_Mutel)\
**Post date:** [30 November 2009 21:15 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/1 "2009-11-30T21:15:35Z")

</div>

I'm trying to get a constant inside a class (but i have to do it outside  
the declaration)

module A  
&nbsp;&nbsp;class B  
&nbsp;&nbsp;end  
&nbsp;&nbsp;class C  
&nbsp;&nbsp;end  
end

How to get constant B from inside C but executed from outside first  
declaration?  
After module A is declared, trying :

> > > puts A::C.class\_eval("B")

failed and const\_get is not working too.

But if i do something like this:  
module A  
&nbsp;&nbsp;class B  
&nbsp;&nbsp;end  
&nbsp;&nbsp;class C  
&nbsp;&nbsp;&nbsp;&nbsp;$test\_binding = binding  
&nbsp;&nbsp;end  
end

puts eval("B",$test\_binding)

it's working... Is using the binding is the only way to get correct  
scope and resolve constant correctly from inside class C?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Paul\_Harrington1](https://avatars.discourse-cdn.com/v4/letter/p/da6949/32.png) [@Paul\_Harrington1](https://rubytalk.org/u/Paul_Harrington1)\
**Post date:** [30 November 2009 22:20 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/2 "2009-11-30T22:20:22Z")

</div>

Your goal is confusing. module A contains the "B" constant, not class  
C. How does "A::B" not satisfy your needs? What exactly are you trying  
to do?

> **···**
>
> On Nov 30, 4:15 pm, Alexandre Mutel \<alexandre\_mu...@yahoo.fr\> wrote:
> 
> > I'm trying to get a constant inside a class (but i have to do it outside  
> > the declaration)
> > 
> > module A  
> > class B  
> > end  
> > class C  
> > end  
> > end
> > 
> > How to get constant B from inside C but executed from outside first  
> > declaration?  
> > After module A is declared, trying :
> > 
> > \>\>\> puts A::C.class\_eval("B")
> > 
> > failed and const\_get is not working too.

---

<div class="post-metadata">

**Author:** ![Alexandre\_Mutel](https://avatars.discourse-cdn.com/v4/letter/a/db5fbb/32.png) [@Alexandre\_Mutel](https://rubytalk.org/u/Alexandre_Mutel)\
**Post date:** [30 November 2009 22:35 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/3 "2009-11-30T22:35:14Z")

</div>

pharrington wrote:

> > How to get constant B from inside C but executed from outside first  
> > declaration?  
> > After module A is declared, trying :
> > 
> > \>\>\> puts A::C.class\_eval("B")
> > 
> > failed and const\_get is not working too.
> 
> Your goal is confusing. module A contains the "B" constant, not class  
> C. How does "A::B" not satisfy your needs? What exactly are you trying  
> to do?

Sorry for the shortcut in my explanation. In fact, my test case is a bit  
more dynamic. I'm developing a DSL that evaluate blocks that can contain  
a line like this:  
A\_CONSTANT some,args,...etc.

So i'm trying to get the constant dynamically and not statically :

I have something like :  
class ConstSearcher  
&nbsp;&nbsp;&nbsp;def self.method\_missing(sym,\*args)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts const\_get(sym)  
&nbsp;&nbsp;&nbsp;end  
end

module A  
&nbsp;&nbsp;&nbsp;class B  
&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;class C \< ConstSearcher  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts B # \<\< static constant lookup is working  
&nbsp;&nbsp;&nbsp;end  
end

But performing a dynamic lookup is not : A::C.instance\_eval("B 11111")  
:  
NameError: (irb):3:in `const\_get': uninitialized constant A::C::B  
&nbsp;&nbsp;from (irb):13  
&nbsp;&nbsp;from (irb):3:in `method\_missing'  
&nbsp;&nbsp;from (eval):1

i tried several methods (eval with binding...etc.) without any success.  
Does i have to loop through parent modules and perform a const\_get on  
each module ? (generating a huge performance penalty).

> **···**
>
> > On Nov 30, 4:15�pm, Alexandre Mutel \<alexandre\_mu...@yahoo.fr\> wrote:
> 
> &nbsp;&nbsp;from :0  
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Alexandre\_Mutel](https://avatars.discourse-cdn.com/v4/letter/a/db5fbb/32.png) [@Alexandre\_Mutel](https://rubytalk.org/u/Alexandre_Mutel)\
**Post date:** [30 November 2009 22:47 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/4 "2009-11-30T22:47:31Z")

</div>

Currently, i'm using something like

class Module  
&nbsp;&nbsp;def dyn\_const\_get(sym)  
&nbsp;&nbsp;&nbsp;&nbsp;list = name.split('::').inject([Object]) {|hierarchy,name| hierarchy  
\<\< hierarchy.last.const\_get(name)}  
&nbsp;&nbsp;&nbsp;&nbsp;result = nil  
&nbsp;&nbsp;&nbsp;&nbsp;while !list.empty? && result.nil?  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lookup\_in = list.pop  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result = lookup\_in.const\_get sym  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;result  
&nbsp;&nbsp;end  
end

And performing : A::C.dyn\_const\_get(:B) returns

But that's a very bad option in terms of performance... I'm wondering if  
there are any other options?

> **···**
>
> A::B  
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Rob\_Biedenharn1](https://avatars.discourse-cdn.com/v4/letter/r/57b2e6/32.png) [@Rob\_Biedenharn1](https://rubytalk.org/u/Rob_Biedenharn1)\
**Post date:** [30 November 2009 22:59 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/5 "2009-11-30T22:59:31Z")

</div>

Would your DSL rather do something with const\_missing instead of method\_missing? (see Module#const\_missing) I suppose that you could set A::C::B = A::B

-Rob

Rob Biedenharn [http://agileconsultingllc.com](http://agileconsultingllc.com)  
Rob@AgileConsultingLLC.com

> **···**
>
> On Nov 30, 2009, at 5:47 PM, Alexandre Mutel wrote:
> 
> > Currently, i'm using something like
> > 
> > class Module  
> > def dyn\_const\_get(sym)  
> > &nbsp;&nbsp;&nbsp;list = name.split('::').inject([Object]) {|hierarchy,name| hierarchy  
> > \<\< hierarchy.last.const\_get(name)}  
> > &nbsp;&nbsp;&nbsp;result = nil  
> > &nbsp;&nbsp;&nbsp;while !list.empty? && result.nil?  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lookup\_in = list.pop  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result = lookup\_in.const\_get sym  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;result  
> > end  
> > end
> > 
> > And performing : A::C.dyn\_const\_get(:B) returns  
> > A::B
> > 
> > But that's a very bad option in terms of performance... I'm wondering if  
> > there are any other options?  
> > --  
> > Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Paul\_Harrington1](https://avatars.discourse-cdn.com/v4/letter/p/da6949/32.png) [@Paul\_Harrington1](https://rubytalk.org/u/Paul_Harrington1)\
**Post date:** [30 November 2009 23:00 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/6 "2009-11-30T23:00:15Z")

</div>

As far as I know the only way to do this is to traverse the  
inheritance hierarchy :\

> **···**
>
> On Nov 30, 5:47 pm, Alexandre Mutel \<alexandre\_mu...@yahoo.fr\> wrote:
> 
> > Currently, i'm using something like
> > 
> > class Module  
> > def dyn\_const\_get(sym)  
> > list = name.split('::').inject([Object]) {|hierarchy,name| hierarchy  
> > \<\< hierarchy.last.const\_get(name)}  
> > result = nil  
> > while !list.empty? && result.nil?  
> > begin  
> > lookup\_in = list.pop  
> > result = lookup\_in.const\_get sym  
> > rescue  
> > end  
> > end  
> > result  
> > end  
> > end
> > 
> > And performing : A::C.dyn\_const\_get(:B) returns  
> > A::B
> > 
> > But that's a very bad option in terms of performance... I'm wondering if  
> > there are any other options?  
> > --  
> > Posted viahttp://www.ruby-forum.com/.

---

<div class="post-metadata">

**Author:** ![Alexandre\_Mutel](https://avatars.discourse-cdn.com/v4/letter/a/db5fbb/32.png) [@Alexandre\_Mutel](https://rubytalk.org/u/Alexandre_Mutel)\
**Post date:** [30 November 2009 23:10 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/7 "2009-11-30T23:10:40Z")

</div>

pharrington wrote:

> > � � � � result = lookup\_in.const\_get sym  
> > But that's a very bad option in terms of performance... I'm wondering if  
> > there are any other options?  
> > --  
> > Posted viahttp://www.ruby-forum.com/.
> 
> As far as I know the only way to do this is to traverse the  
> inheritance hierarchy :\

Ok, so that's a bad news...

Rob wrote:

> Would your DSL rather do something with const\_missing instead of  
> method\_missing? (see Module#const\_missing) I suppose that you could  
> set A::C::B = A::B  
> -Rob

Nope, because the block I'm trying to evaluate is "A\_CONSTANT  
some,parameters", so i expect to parse the parameters as well for this  
constant. Moreover, the const\_missing doesn't solve the issue as i still  
have to lookup through parent's modules to get the constant dynamically  
as it is performed statically...

> **···**
>
> > On Nov 30, 5:47�pm, Alexandre Mutel \<alexandre\_mu...@yahoo.fr\> wrote:
> 
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Paul\_Harrington1](https://avatars.discourse-cdn.com/v4/letter/p/da6949/32.png) [@Paul\_Harrington1](https://rubytalk.org/u/Paul_Harrington1)\
**Post date:** [30 November 2009 23:45 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/8 "2009-11-30T23:45:06Z")

</div>

If constant lookup is causing a significant impact on your project's  
performance, mayhaps a good idea would be to create a tree of commonly  
used constants (whatever that means for your app) for fast lookup?

> **···**
>
> On Nov 30, 6:10 pm, Alexandre Mutel \<alexandre\_mu...@yahoo.fr\> wrote:
> 
> > pharrington wrote:  
> > \> On Nov 30, 5:47 pm, Alexandre Mutel \<alexandre\_mu...@yahoo.fr\> wrote:  
> > \>\> result = lookup\_in.const\_get sym  
> > \>\> But that's a very bad option in terms of performance... I'm wondering if  
> > \>\> there are any other options?  
> > \>\> --  
> > \>\> Posted viahttp://www.ruby-forum.com/.
> > 
> > \> As far as I know the only way to do this is to traverse the  
> > \> inheritance hierarchy :\
> > 
> > Ok, so that's a bad news...
> > 
> > Rob wrote:  
> > \>Would your DSL rather do something with const\_missing instead of  
> > \>method\_missing? (see Module#const\_missing) I suppose that you could  
> > \>set A::C::B = A::B  
> > \>-Rob
> > 
> > Nope, because the block I'm trying to evaluate is "A\_CONSTANT  
> > some,parameters", so i expect to parse the parameters as well for this  
> > constant. Moreover, the const\_missing doesn't solve the issue as i still  
> > have to lookup through parent's modules to get the constant dynamically  
> > as it is performed statically...
> > 
> > --  
> > Posted viahttp://www.ruby-forum.com/.

---

<div class="post-metadata">

**Author:** ![Alexandre\_Mutel](https://avatars.discourse-cdn.com/v4/letter/a/db5fbb/32.png) [@Alexandre\_Mutel](https://rubytalk.org/u/Alexandre_Mutel)\
**Post date:** [1 December 2009 14:53 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/9 "2009-12-01T14:53:49Z")

</div>

Just a general remark about this problem. Shouldn't Ruby have a builtin  
mechanism to resolve dynamically and efficiently constants handling  
lexical scopes correctly?

Seems that in 1.9, we have this features:  
irb(main):001:0\> class A  
irb(main):002:1\> BAR = 1  
irb(main):003:1\> class B  
irb(main):004:2\> def self.foo(&b)  
irb(main):005:3\> instance\_eval(&b)  
irb(main):006:3\> end  
irb(main):007:2\> end  
irb(main):008:1\> end  
=\> nil  
irb(main):009:0\> A::B.foo do  
irb(main):010:1\* puts BAR  
irb(main):011:1\> end  
1  
=\> nil  
irb(main):012:0\>

BUT now, try to do it with const\_get, and we got a NameError:  
irb(main):012:0\> A::B.foo do  
irb(main):013:1\* puts const\_get(:BAR)  
irb(main):014:1\> end  
NameError: uninitialized constant A:🅱:BAR  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):13:in `const\_get'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):13:in `block in irb\_binding'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):5:in `instance\_eval'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):5:in `foo'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):12  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from E:/Code/Ruby/bin/irb:12:in `\<main\>'

This is quite frustrating when writing a DSL language to not being able  
to resolve constants dynamically (without getting a costly module  
hierarchy and checking the constant in each module...)

Should'nt this constant lookup be consistent between static and  
const\_get?

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Walton\_Hoops1](https://avatars.discourse-cdn.com/v4/letter/w/77aa72/32.png) [@Walton\_Hoops1](https://rubytalk.org/u/Walton_Hoops1)\
**Post date:** [1 December 2009 17:38 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/10 "2009-12-01T17:38:35Z")

</div>

> From: alexandre\_mutel@yahoo.fr [mailto:alexandre\_mutel@yahoo.fr]  
> Just a general remark about this problem. Shouldn't Ruby have a builtin  
> mechanism to resolve dynamically and efficiently constants handling  
> lexical scopes correctly?
> 
> Seems that in 1.9, we have this features:  
> irb(main):001:0\> class A  
> irb(main):002:1\> BAR = 1  
> irb(main):003:1\> class B  
> irb(main):004:2\> def self.foo(&b)  
> irb(main):005:3\> instance\_eval(&b)  
> irb(main):006:3\> end  
> irb(main):007:2\> end  
> irb(main):008:1\> end  
> =\> nil  
> irb(main):009:0\> A::B.foo do  
> irb(main):010:1\* puts BAR  
> irb(main):011:1\> end  
> 1  
> =\> nil  
> irb(main):012:0\>
> 
> BUT now, try to do it with const\_get, and we got a NameError:  
> irb(main):012:0\> A::B.foo do  
> irb(main):013:1\* puts const\_get(:BAR)  
> irb(main):014:1\> end  
> NameError: uninitialized constant A:🅱:BAR  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):13:in `const\_get'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):13:in `block in irb\_binding'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):5:in `instance\_eval'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):5:in `foo'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):12  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from E:/Code/Ruby/bin/irb:12:in `\<main\>'
> 
> This is quite frustrating when writing a DSL language to not being able  
> to resolve constants dynamically (without getting a costly module  
> hierarchy and checking the constant in each module...)

irb(main):001:0\> class A  
irb(main):002:1\> BAR=1  
irb(main):003:1\> class B  
irb(main):004:2\> def self.foo(&b)  
irb(main):005:3\> instance\_eval(&b)  
irb(main):006:3\> end  
irb(main):007:2\> end  
irb(main):008:1\> end  
=\> nil  
irb(main):012:0\> A::B.foo do  
irb(main):013:1\* puts eval('BAR')  
irb(main):014:1\> end  
1  
=\> nil

Done. A more experienced Rubist may be able to do it without eval, but  
that works.

> Should'nt this constant lookup be consistent between static and  
> const\_get?

No, that's not what const\_get is for. It's operating on a class  
not a scope. That's why it's an instance method. The way you  
calling it is literally equivalent too:

In other words, you are asking for \_B's\_ constants. Since B,  
nor any of its ancestors have the constant BAR, an error occurs.

Maybe this demonstrates more clearly what I mean:

irb(main):001:0\> class A  
irb(main):002:1\> BAR=1  
irb(main):003:1\> def self.BAR  
irb(main):004:2\> BAR  
irb(main):005:2\> end  
irb(main):006:1\> class B  
irb(main):007:2\> end  
irb(main):008:1\> end  
=\> nil  
irb(main):009:0\> A.BAR  
=\> 1  
irb(main):011:0\> A::B.BAR  
NoMethodError: undefined method `BAR' for A:🅱Class  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):11  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from C:/Ruby19/bin/irb:12:in `\<main\>'  
irb(main):012:0\> A.const\_get :BAR  
=\> 1  
irb(main):013:0\> A::B.const\_get :BAR  
NameError: uninitialized constant A:🅱:BAR  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):13:in `const\_get'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):13  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from C:/Ruby19/bin/irb:12:in `\<main\>'  
irb(main):014:0\>

Notice, const\_get works the same as the accessor method  
for BAR.

> **···**
>
> > -----Original Message-----
> 
> A::B.const\_get(:BAR)

---

<div class="post-metadata">

**Author:** ![Alexandre\_Mutel](https://avatars.discourse-cdn.com/v4/letter/a/db5fbb/32.png) [@Alexandre\_Mutel](https://rubytalk.org/u/Alexandre_Mutel)\
**Post date:** [1 December 2009 18:32 UTC](https://rubytalk.org/t/problem-trying-to-get-a-constant-with-correct-scope/56434/11 "2009-12-01T18:32:47Z")

</div>

Walton Hoops wrote:

> irb(main):012:0\> A::B.foo do  
> irb(main):013:1\* puts eval('BAR')  
> irb(main):014:1\> end  
> 1  
> =\> nil
> 
> Done. A more experienced Rubist may be able to do it without eval, but  
> that works.

Oh, thanks, at least the eval is working on constants with 1.9, this is  
good to know.

> > Should'nt this constant lookup be consistent between static and  
> > const\_get?
> 
> No, that's not what const\_get is for. It's operating on a class  
> not a scope. That's why it's an instance method. The way you  
> calling it is literally equivalent too:
> 
> A::B.const\_get(:BAR)
> 
> In other words, you are asking for \_B's\_ constants. Since B,  
> nor any of its ancestors have the constant BAR, an error occurs.

I understand the current const\_get behavior, but still, it would be nice  
to have something equivalent to fully resolving a constant in a faster  
way without going through the eval way.

I was thinking about a const\_get with an aditionnal parameter like  
def const\_get(symbol, check\_module\_hierarchy=false) {}, still living  
this method in the module.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).
