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
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:
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:
: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)