Problem trying to get a constant with correct scope

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.

But if i do something like this:
module A
  class B
  end
  class C
    $test_binding = binding
  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/\.

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.

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
   def self.method_missing(sym,*args)
        puts const_get(sym)
   end
end

module A
   class B
   end
   class C < ConstSearcher
       puts B # << static constant lookup is working
   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
  from (irb):13
  from (irb):3:in `method_missing'
  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:

  from :0
--
Posted via http://www.ruby-forum.com/\.

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

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/.

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
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)
   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 via http://www.ruby-forum.com/\.

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/.

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/\.

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/.

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::b::BAR
        from (irb):13:in `const_get'
        from (irb):13:in `block in irb_binding'
        from (irb):5:in `instance_eval'
        from (irb):5:in `foo'
        from (irb):12
        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/.

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::b::BAR
        from (irb):13:in `const_get'
        from (irb):13:in `block in irb_binding'
        from (irb):5:in `instance_eval'
        from (irb):5:in `foo'
        from (irb):12
        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::b:Class
        from (irb):11
        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::b::BAR
        from (irb):13:in `const_get'
        from (irb):13
        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)

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/\.