Forum: Ruby-core Question on scoped constant resolution Class vs Module

Posted by Peter McLain (Guest)
on 2010-03-04 20:33
(Received via mailing list)
I asked this on ruby-talk, but didn't get anywhere.  Someone suggested
I post over here.

Resolution of fully scoped constants behaves differently if there is a
class versus a module in the name:

   XYZ = 10

   module M
   end

   class C
   end

   p defined? M::XYZ  # => nil
   p defined? C::XYZ  # => "constant"

A few questions:

1: Is this difference intended?
2: If so, what is the rationale?
3: Should defined?(C::XYZ) behave differently than C.const_defined?
(:XYZ) ?
4: Is the draft ruby spec correct, or MRI behavior correct, or did I
miss something in the following:

I think the behavior with M::XYZ does not conform to section 11.4.3.2
of the draft ruby spec:

11.4.3.2
  (a) the primary-expression is M,
  (b) M is a module, do not raise TypeError
  (c 1) XYZ is the constant-identifier
  (c 2) XYZ is not one of the constants defined in M
  (c 3 i) There are no included modules in M (skip)
  (c 3 ii) N/A
  (c 3 iii) Goto step e of section 11.4.3.1

11.4.3.1
  (e) M is not a class
  (e 1) Search Object for a binding for XYZ

So, according to the spec, it looks like M:XYZ should resolve to the
XYZ in Object and MRI is incorrect to return nil.

Did I miss something?


The real world occurrence of this was:

    return unless defined? RDoc::VERSION # RDoc 1 does not have VERSION
    # code that blows up if RDoc 1 being used...

Which does not currently work in MagLev, since MagLev returns
"constant" for defined?RDoc::VERSION.  One could argue that the proper
test, which works for both classes and modules in all ruby
implementations, is:

    return unless RDoc.const_defined? :VERSION

--
Peter McLain
peter.mclain@gemstone.com
Posted by Caleb Clausen (Guest)
on 2010-03-04 21:26
(Received via mailing list)
On 3/4/10, Peter McLain <peter.mclain@gemstone.com> wrote:
> I asked this on ruby-talk, but didn't get anywhere.  Someone suggested
> I post over here.

Here's the original thread on ruby-talk:
http://www.ruby-forum.com/topic/205339
Posted by Yusuke ENDOH (Guest)
on 2010-03-06 17:07
(Received via mailing list)
Hi Peter,

2010/3/5 Peter McLain <peter.mclain@gemstone.com>:
> 1: Is this difference intended?

I think so.


> 2: If so, what is the rationale?

- constant defined in toplevel belongs to Object class
- scoped constant reference tries to find binding towards ancestors
- ancestors of M does not include Object (M does not inherit from
  Object)
- ancestors of C includes Object (C inherits from Object)


> 3: Should defined?(C::XYZ) behave differently than C.const_defined?(:XYZ) ?

Module#const_defined? in 1.8 checks whether there is binding in the
module itself.  Indeed it is not good semantics.  1.9 is improved
so that the method finds binding in all ancestors by default.


> 4: Is the draft ruby spec correct, or MRI behavior correct, or did I miss
> something in the following:

Good point.  I bet the draft is wrong.
But note that the above answers are just my opinions.

Matz or Shugo Maeda, could you please answer this question?
Posted by Peter McLain (Guest)
on 2010-03-10 18:22
(Received via mailing list)
On Mar 6, 2010, at 8:06 AM, Yusuke ENDOH wrote:
>> 4: Is the draft ruby spec correct, or MRI behavior correct, or did  
>> I miss
>> something in the following:
>
> Good point.  I bet the draft is wrong.
> But note that the above answers are just my opinions.
>
> Matz or Shugo Maeda, could you please answer this question?

   If the draft is wrong, then I will file a comment on it, but I will
wait until we get a definitive answer.

   Thanks

--
Peter McLain
peter.mclain@gemstone.com
Posted by Shugo Maeda (Guest)
on 2010-03-11 03:32
(Received via mailing list)
Hi,

Sorry for the delay.
I missed this thread.

2010/3/7 Yusuke ENDOH <mame@tsg.ne.jp>:
>> 4: Is the draft ruby spec correct, or MRI behavior correct, or did I miss
>> something in the following:
>
> Good point.  I bet the draft is wrong.

I agree with you, and will fix the draft.
Is it enough to fix 11.4.3.2 c)-3) as follows?

i) Let L be the included module list of C. Search each element of L in
the reverse order for a binding of a constant with name N.
ii) If the binding is found, the value of the
scoped-constant-reference is the value of the binding.
iii) Otherwise, if C is an instance of the class Class, search for a
binding of a constant with name N from Step e of §11.4.3.1.
iv) Otherwise, create a direct instance of the class Symbol with name
N, and let R be that instance. Invoke the method const_missing on C
with R as the only argument.
Posted by Peter McLain (Guest)
on 2010-03-12 02:03
(Received via mailing list)
On Mar 10, 2010, at 6:32 PM, Shugo Maeda wrote:
>
> 2010/3/7 Yusuke ENDOH <mame@tsg.ne.jp>:
>>> 4: Is the draft ruby spec correct, or MRI behavior correct, or did  
>>> I miss
>>> something in the following:
>>
>> Good point.  I bet the draft is wrong.
>
> I agree with you, and will fix the draft.
> Is it enough to fix 11.4.3.2 c)-3) as follows?

   Yes, your wording will fix the spec.  Thanks.

--
Peter McLain
peter.mclain@gemstone.com
Posted by Shugo Maeda (Guest)
on 2010-03-12 02:07
(Received via mailing list)
Hello,

2010/3/12 Peter McLain <peter.mclain@gemstone.com>:
>  Yes, your wording will fix the spec.  Thanks.

I have fixed it.  Thank you.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.