Const_defined? not quite in sync with const_get?

Assuming the following snippet, I'd expect Foo::const_defined?(:Bar)
to be routed via Foo::const_missing. Instead it resolves to top-level
Bar. Can someone explain why please?

--code--

class Bar
end

module Foo
  def self.const_missing(konst)
    puts "missing konst #{konst}"
  end
end

Foo::Bar
#=> missing konst Bar # Unsurprising behaviour

p Foo::const_defined?(:Bar)
false # Unsurprising behaviour

p Foo::const_get(:Bar)
#=> Bar # Surprising behaviour

--/code--

Cheers,

Chris

non-prefixed constants follow the normal scoping rules:

harp:~ > cat a.rb
class Bar
end

module Foo
   def self.const_missing(konst)
     puts "missing konst #{konst}"
   end
end

Foo::Bar
#=> missing konst Bar # Unsurprising behaviour

p Foo::const_defined?('Bar')
false # Unsurprising behaviour

p Foo::const_get('Foo::Bar')
# ^^^^^
#=> Bar # Surprising behaviour

harp:~ > ruby a.rb
missing konst Bar
false
a.rb:16:in `const_get': wrong constant name Foo::Bar (NameError)
         from a.rb:16

-a

···

On Thu, 21 Sep 2006, Chris Roos wrote:

Assuming the following snippet, I'd expect Foo::const_defined?(:Bar)
to be routed via Foo::const_missing. Instead it resolves to top-level
Bar. Can someone explain why please?

--code--

class Bar
end

module Foo
def self.const_missing(konst)
  puts "missing konst #{konst}"
end

Foo::Bar
#=> missing konst Bar # Unsurprising behaviour

p Foo::const_defined?(:Bar)
false # Unsurprising behaviour

p Foo::const_get(:Bar)
#=> Bar # Surprising behaviour

--/code--

Cheers,

Chris

--
in order to be effective truth must penetrate like an arrow - and that is
likely to hurt. -- wei wu wei

Posted: Wed, 20 Sep 2006 18:06:54 +0100

···

Date: Thu, 21 Sep 2006 02:06:56 +0900
From: "Chris Roos" <chrisjroos@gmail.com>
Reply-To: ruby-talk@ruby-lang.org
Subject: const_defined? not quite in sync with const_get ??
To: ruby-talk@ruby-lang.org (ruby-talk ML)
Message-Id: <3a5e51050609201006j5dc6449cyae74e71099fb3f52@mail.gmail.com>
X-ML-Name: ruby-talk
X-Mail-Count: 215393

2006/9/21, Chris Roos <chrisjroos@gmail.com>:

Assuming the following snippet, I'd expect Foo::const_defined?(:Bar)
to be routed via Foo::const_missing. Instead it resolves to top-level
Bar. Can someone explain why please?

--code--

class Bar
end

module Foo
  def self.const_missing(konst)
    puts "missing konst #{konst}"
  end
end

Foo::Bar
#=> missing konst Bar # Unsurprising behaviour

p Foo::const_defined?(:Bar)
false # Unsurprising behaviour

p Foo::const_get(:Bar)
#=> Bar # Surprising behaviour

--/code--

Cheers,

Chris

--
なかだです。

--
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

Hi,

Sorry for mispost.

At Thu, 21 Sep 2006 02:06:56 +0900,
Chris Roos wrote in [ruby-talk:215393]:

Foo::Bar
#=> missing konst Bar # Unsurprising behaviour

p Foo::const_defined?(:Bar)
false # Unsurprising behaviour

p Foo::const_get(:Bar)
#=> Bar # Surprising behaviour

It has changed in 1.9.

  p Foo::const_defined?(:Bar) #=> true

  p Foo::const_get(:Bar) #=> Bar

  p Foo::const_defined?(:Bar, false) #=> false

  p Foo::const_get(:Bar, false) #=> missing konst Bar

···

--
Nobu Nakada

non-prefixed constants follow the normal scoping rules:

Thanks for the clarification. Purely out of interest, do you find
this behaviour a bit odd (or am I missing obvious reasons as to why it
is implemented this way)?

Chris

so that

   class C
     a = Array.new # up scope
   end

and

   class C
     a = const_get('Array').new
   end

behave

i agree it can be confusing, but the alternative, requiring all constants to
be fully scoped, would be an enormous pain in the ass.

cheers.

-a

···

On Thu, 21 Sep 2006, Chris Roos wrote:

non-prefixed constants follow the normal scoping rules:

Thanks for the clarification. Purely out of interest, do you find
this behaviour a bit odd (or am I missing obvious reasons as to why it
is implemented this way)?

Chris

--
in order to be effective truth must penetrate like an arrow - and that is
likely to hurt. -- wei wu wei

so that

   class C
     a = Array.new # up scope
   end

and

   class C
     a = const_get('Array').new
   end

behave

i agree it can be confusing, but the alternative, requiring all constants to
be fully scoped, would be an enormous pain in the ass.

Ah, of course, that makes sense. Cheers.