Created
January 12, 2012 07:10
-
-
Save shugo/1599198 to your computer and use it in GitHub Desktop.
How to invoke Module#constants on Module itself
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Module.constants returns constants accessible at the place where the | |
# method is called. | |
class A | |
X = 1 | |
p Module.constants.include?(:X) #=> true | |
end | |
# Module#constants returns constants defined in the receiver. However, | |
# you need a trick to invoke Module#constants on Module itself. | |
p Module.instance_method(:constants).bind(Module).call #=> [] | |
# Another way to invoke Module#constants on Module itself suggested by | |
# Marc-Andre Lafortune in [ruby-core:42091] | |
# It's available only in CRuby 1.9, and I doubt that Matz has accepted the | |
# feature because it has been introduced by nobu secretly. | |
p Module.constants(Module) |
Good point. So I guess the clearest demonstration would be:
class A
X = 1
p Module.constants.include?(:X) #=> true
end
p Module.constants.include?(:X) #=> false
And I think Module.instance_method(:constants).bind(Module).call
is actually a totally different function, which is defined in variable.c:1775 (from ruby-1.9.3-p0)
https://github.com/ruby/ruby/blob/v1_9_3_0/variable.c#L1775-1809 rb_mod_constants (Module#constants)
https://github.com/ruby/ruby/blob/v1_9_3_0/eval.c#L286-328 rb_mod_s_constants (Module.constants)
I guess rb_mod_s_constants
is overriding rb_mod_constants
inside Module
,
and which will also call rb_mod_constants
when argv > 0
.
This is so confusing :o
Thanks for the discussion.
/*
* call-seq:
* mod.constants(inherit=true) -> array
*
* Returns an array of the names of the constants accessible in
* <i>mod</i>. This includes the names of constants in any included
* modules (example at start of section), unless the <i>all</i>
* parameter is set to <code>false</code>.
*
* IO.constants.include?(:SYNC) #=> true
* IO.constants(false).include?(:SYNC) #=> false
*
* Also see <code>Module::const_defined?</code>.
*/
VALUE
rb_mod_constants(int argc, VALUE *argv, VALUE mod)
{
VALUE inherit;
st_table *tbl;
if (argc == 0) {
inherit = Qtrue;
}
else {
rb_scan_args(argc, argv, "01", &inherit);
}
if (RTEST(inherit)) {
tbl = rb_mod_const_of(mod, 0);
}
else {
tbl = rb_mod_const_at(mod, 0);
}
return rb_const_list(tbl);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You said "the latter would return all the names in the TOPLEVEL_BINDING", but it's wrong.
Module.constants returns all the constant names accessible at the place where Module.constant is called.
Please read my original gist. :X is included in the result of Module.constants even if X is not accessible at top level.