Project

General

Profile

Actions

Bug #5887

closed

The documentation of Module.constants is incorrect

Added by shugo (Shugo Maeda) over 12 years ago. Updated almost 12 years ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 2.0.0dev (2012-01-12 trunk 34015) [i686-linux]
Backport:
[ruby-core:42080]

Description

The documentation of Module.constants says "Returns an array of the names of all constants defined in the system. This list includes the names of all modules and classes." However, Module.constants returns the names of the constants accessible at the place where the method is called:

class A
X = 1
p Module.constants.include?(:X) #=> true
end

Could someone fix the documentation? I can't write a proper English documentation.

OT: I think Module.constants should be renamed in the future, because Module.constants is confusing with Module#constants. Why the hell do I have to write the following tricky code to invoke Module#constants on Module itself?

p Module.instance_method(:constants).bind(Module).call

Updated by naruse (Yui NARUSE) over 12 years ago

  • Status changed from Open to Assigned
  • Assignee set to drbrain (Eric Hodel)

Updated by marcandre (Marc-Andre Lafortune) over 12 years ago

Shugo Maeda wrote:

OT: I think Module.constants should be renamed in the future, because Module.constants is confusing with Module#constants. Why the hell do I have to write the following tricky code to invoke Module#constants on Module itself?

p Module.instance_method(:constants).bind(Module).call

Actually, you can simply pass a parameter to Module.constants and the singleton method will call the instance method. The documentation should definitely reflect this too...

I'll try to improve the doc.

Updated by shugo (Shugo Maeda) over 12 years ago

Hi,

2012/1/13 Marc-Andre Lafortune :

OT: I think Module.constants should be renamed in the future, because Module.constants is confusing with Module#constants.  Why the hell do I have to write the following tricky code to invoke Module#constants on Module itself?

  p Module.instance_method(:constants).bind(Module).call

Actually, you can simply pass a parameter to Module.constants and the singleton method will call the instance method. The documentation should definitely reflect this too...

Oh, I didn't know that. However, I doubt that Matz has accepted the feature.

The optional arguments of Module.constants were introduced by nobu in
r11338, but the change of Module.constants was not described in the
commit log.

 * intern.h, object.c, variable.c (rb_mod_constants): added an optional
   flag to search ancestors, which is defaulted to true, as well as
   const_defined? and const_get.  [ruby-dev:29989]

It was not discussed in the thread starting from [ruby-dev:29989] either.

Is it an official feature?

--
Shugo Maeda

Updated by marcandre (Marc-Andre Lafortune) over 12 years ago

  • Category changed from doc to core
  • Assignee changed from drbrain (Eric Hodel) to matz (Yukihiro Matsumoto)

Oh, ok. Let's wait for Matz to confirm this feature.

Updated by shugo (Shugo Maeda) about 12 years ago

shugo (Shugo Maeda) wrote:

Actually, you can simply pass a parameter to Module.constants and the singleton method will call the instance method. The documentation should definitely reflect this too...

Oh, I didn't know that. However, I doubt that Matz has accepted the feature.

The optional arguments of Module.constants were introduced by nobu in
r11338, but the change of Module.constants was not described in the
commit log.

 * intern.h, object.c, variable.c (rb_mod_constants): added an optional
   flag to search ancestors, which is defaulted to true, as well as
   const_defined? and const_get.  [ruby-dev:29989]

It was not discussed in the thread starting from [ruby-dev:29989] either.

Is it an official feature?

What do you think of this feature, Matz?
The following code illustrates the current behavior of Module.constants.

module A
C1 = 1
end
class Module
include A
C2 = 2
end
module B
C3 = 3
# with no argument, get constants available here
p Module.constants #=> [:C3, :Object, :Module, :Class, ...
# with an argument, the same behavior as Module#constants
p Module.constants(false) #=> [:C2]
p Module.constants(true) #=> [:C2, :C1]
end

I don't think this code is readable.
It's better to have an alias of Module#constants such as `defined_constants' to avoid the name conflict.

Updated by ko1 (Koichi Sasada) almost 12 years ago

  • Assignee changed from matz (Yukihiro Matsumoto) to shugo (Shugo Maeda)

Matz, do you think about it?

Updated by matz (Yukihiro Matsumoto) almost 12 years ago

  • Status changed from Assigned to Closed

The document has been fixed already:

In the first form, returns an array of the names of all
constants accessible from the point of call.
This list includes the names of all modules and classes
defined in the global scope.

If you are going to propose alternative name for Module.constant, submit a feature request.
It might be difficult due to the compatibility rule.

Matz.

Updated by fxn (Xavier Noria) almost 12 years ago

I think this description could be better.

On one hand I find a little surprising that the first sentence mentions constants accessible at some point, whereas Module.constants returns top-level constants even if called in a subclass of BasicObject.

On the other hand, in addition to the names of classes and modules in the global scope, RUBY_PLATFORM, RbConfig, etc. are also returned.

And, to be more exact, the method returns the name of the top-level constants, which may or may not coincide with the name of the classes or modules they store. See for example

class C
end

D = C
Object.instance_eval { remove_const(:C) }

p ::Module.constants.sort # contains :D, not :C

I could volunteer a patch with an alternative if it sounds good.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0