A little challenge - reproduce this error

Want to see a really amazing error I got this week? Okay… but to
make it more interesting I am going to the change some names to
protect the innocent, and offer up a little challenge: How can
reproduce it?

The error is this:

uninitialized constant X::Foo::X (NameError)

Did you catch that?

Think you can solve it?

I imagine your mind is getting a bit mushy about now :wink:

throw NameError.new(“uninitialized constant X::Foo::X”)

This is a pretty trivial error to generate. Just reference the
constant that doesn’t exist:

$ irb
ruby-1.9.2-p180 :001 > module X; module Foo; end; end
=> nil
ruby-1.9.2-p180 :002 > X::Foo::X
NameError: uninitialized constant X::Foo::X

~ jf

John F.
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: http://stackoverflow.com/users/75170/

On Jun 8, 9:20am, John F. [email protected] wrote:

This is a pretty trivial error to generate. Just reference the
constant that doesn’t exist:

$ irb
ruby-1.9.2-p180 :001 > module X; module Foo; end; end
=> nil
ruby-1.9.2-p180 :002 > X::Foo::X
NameError: uninitialized constant X::Foo::X

Ah good point. I made an assumption. A qualifier then: X does exist.
How about this must be as top of your solution.

module X; end

On Wed, Jun 8, 2011 at 6:43 AM, Intransition [email protected]
wrote:

NameError: uninitialized constant X::Foo::X

Ah good point. I made an assumption. A qualifier then: X does exist.
How about this must be as top of your solution.

module X; end

The top-level X (and the Foo underneath it) seems required to get the
error, so that doesn’t make it harder. If you reference X::Foo::X
without X existing, you’ll get
uninitialized constant Object::X (NameError)

If you reference X::Foo::X with just the part you have above, you’ll
get uninitialized constant X::Foo (NameError)

The easiest way to get the error you ask about is
module X; module Foo; end; end
X::Foo::X

But I would guess that that probably isn’t what you are looking for
either.

On Wed, Jun 8, 2011 at 6:16 AM, Steve K. [email protected]
wrote:

throw NameError.new(“uninitialized constant X::Foo::X”)

Doesn’t give the right result. You want raise, not throw.

On Jun 8, 9:16am, Steve K. [email protected] wrote:

throw NameError.new(“uninitialized constant X::Foo::X”)

Oh you are a clever one :wink:

On Jun 8, 2011, at 10:56 AM, Christopher D. wrote:

The easiest way to get the error you ask about is
module X; module Foo; end; end
X::Foo::X

But I would guess that that probably isn’t what you are looking for either.

It wouldn’t be, because that’s not an error: it ends up referencing the
top-level X from inside Foo, giving this warning:

(irb):1407: warning: toplevel constant X referenced by X::Foo::X

Michael E.
[email protected]
http://carboni.ca/

On Jun 8, 10:56am, Christopher D. [email protected] wrote:

module X; module Foo; end; end
X::Foo::X

Well, Balls. That in itself seems ridiculous, but you are right. I’m
not sure why it raises that though. Maybe the code is silly, but is it
really wrong? Try X::Foo.const_get(:X) and it works fine. Seems
inconsistent, doesn’t it?

But I would guess that that probably isn’t what you are looking for either.

Yes, in the actual code X is being referenced from within Foo but is
not fully qualified.

On Jun 8, 10:59am, Michael E. [email protected] wrote:

(irb):1407: warning: toplevel constant X referenced by X::Foo::X
Interesting. What platform on you on?

Thomas S. wrote in post #1003914:

Think you can solve it?

Here’s one way:

$ irb --simple-prompt

module X
module Foo
self::X
end
end
NameError: uninitialized constant X::Foo::X
from (irb):3
from :0

This is more sensible than it might appear at first. I use self::X
frequently when I want dynamic scope resolution (e.g. use the constant
which belongs to a subclass, rather than the parent class)

On Jun 8, 11:28am, Intransition [email protected] wrote:

Interesting. What platform on you on?

s/on/are/

I’ve always been pretty bad with the typos, but I swear this week I’ve
gone into dyslexic overdrive. My apologies.

On Jun 8, 2011, at 11:28 AM, Intransition wrote:

It wouldn’t be, because that’s not an error: it ends up referencing the
top-level X from inside Foo, giving this warning:

(irb):1407: warning: toplevel constant X referenced by X::Foo::X

Interesting. What platform on you on?

That was on 1.9.2p188. Seems to be a change in 1.9 - I started checking
against other RVM installs
after seeing your response that X::Foo::X gives an error. I could’ve
sworn I understood the differences
in constant resolution between 1.9.2 and 1.8.7… back to the drawing
board there, I guess.

In fact, I can’t even produce that error in 1.9.2.

Michael E.
[email protected]
http://carboni.ca/

On Thu, Jun 09, 2011 at 12:39:56AM +0900, Michael E. wrote:

That was on 1.9.2p188. Seems to be a change in 1.9 - I started checking
against other RVM installs after seeing your response that X::Foo::X
gives an error. I could’ve sworn I understood the differences in
constant resolution between 1.9.2 and 1.8.7… back to the drawing
board there, I guess.

In fact, I can’t even produce that error in 1.9.2.

It works the same both 1.8.7, 1.9.1, and 1.9.2 for me.

On Jun 8, 2011, at 12:19 PM, Chad P. wrote:

It works the same both 1.8.7, 1.9.1, and 1.9.2 for me.


Chad P. [ original content licensed OWL: http://owl.apotheon.org ]

… and my contribution becomes meaningless. Ugh. I closed my irb
session and re-opened
it, and now can’t repro the top-level dereference. If I can, I’ll post,
but I’m guessing I should
have just used a fresh session instead one that appears to have been
1500 evaluations deep.

Sorry for the confusion/noise,

Michael E.
[email protected]
http://carboni.ca/

On Wed, Jun 8, 2011 at 7:59 AM, Michael E. [email protected] wrote:

On Wed, Jun 8, 2011 at 8:27 AM, Intransition [email protected]
wrote:

The easiest way to get the error you ask about is
module X; module Foo; end; end
X::Foo::X

Well, Balls. That in itself seems ridiculous, but you are right. I’m
not sure why it raises that though. Maybe the code is silly, but is it
really wrong? Try X::Foo.const_get(:X) and it works fine. Seems
inconsistent, doesn’t it?

Not really. I’d expect X::Foo::X to get the constant at that path
(which doesn’t exist, hence the error), while X::Foo.const_get(:X) I’d
expect to resolve as if X was referenced within X::Foo, including
climbing up the chain, and to return the top-level X.

But I would guess that that probably isn’t what you are looking for
either.

Yes, in the actual code X is being referenced from within Foo but is
not fully qualified.

I could swear that I have run into that error in some things in the
past (and resolved it by fully qualifying the affected references),
but now I can’t figure out how to reproduce it.

Christopher D. wrote in post #1004068:

X::Foo.const_get(:X) I’d
expect to resolve as if X was referenced within X::Foo, including
climbing up the chain, and to return the top-level X.

That’s a pain, I have in the past used modules to limit access to only a
predefined set of things:

module Safe
module Foo; end
module Bar; end
end

dirty = “Foo”
m = Safe.const_get(dirty) # ok

dirty = “Object”
m = Safe.const_get(dirty) # I wanted this to fail

I guess you need to build an explicit Hash.

Yes, in the actual code X is being referenced from within Foo but is
not fully qualified.

Is it partially qualified, or a completely bare ‘X’?

Partially qualified is easy to reproduce:

module X; module Foo; Foo::X; end; end
NameError: uninitialized constant X::Foo::X
from (irb):1
from :0

Note there is a subtle difference with the following:

module X::Foo; Foo::X; end
NameError: uninitialized constant X::Foo::Foo
from (irb):4
from :0

I don’t think that’s the issue here, but I was once caught out by the
difference between

module A; module B; …; end; end

and

module A::B; …; end

I think the problem which bit me was this:

module X
module A; end
module B; end
end
=> nil

module X; module A; B; end; end
=> X::B

module X::A; B; end
NameError: uninitialized constant X::a::B
from (irb):6

But it’s not the same as reported in this thread:

module X::A; X; end
=> X

I thought constant lookups would always try in the top-level scope, so I
can’t see how a bare “X” would fail. OTOH, I don’t think I’ve ever seen
any authoritative documentation of the constant lookup rules.

I think the issue which bit me was this:

module Foo
module X
p X # works
end
end

module Foo::X
p X # uninitialized constant Foo::x::X
end

But that’s not the same as reported here. I thought constant lookups
should always try in the top-level scope, so I can’t see how a bare “X”
would fail if there exists a top-level module “X”.

OTOH, I don’t think I’ve ever seen any authoritative documentation of
the constant lookup rules.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs