From: nobuyoshi nakada Date: 2006-01-17T14:15:34+09:00 Subject: [ruby-dev:28225] Re: const_defined? behavior なかだです。 At Mon, 16 Jan 2006 17:05:29 +0900, Daniel Amelang wrote in [ruby-talk:175899]: > Is this the intended behavior of const_defined? > > >> IO::SYNC > => 4096 > >> IO.const_defined? :SYNC > => false > > It appears that const_defined? only returns true if the class is the > originator of the constant. If the constant was borrowed from > somewhere else (in this case, File::Constants), it returns false. Module#const_get でも mod::CONST 形式でも、継承した定数を無視す ることはないので、 const_defined? だけが例外になっています。デ フォルトは const_get に合わせて、省略可能な引数で継承した定数を 無視できるようにするのはどうでしょうか。 method_defined? もちょっと悩ましいですが。 Index: object.c =================================================================== RCS file: /cvs/ruby/src/ruby/object.c,v retrieving revision 1.182 diff -U2 -p -r1.182 object.c --- object.c 12 Dec 2005 03:04:53 -0000 1.182 +++ object.c 17 Jan 2006 05:09:58 -0000 @@ -1629,20 +1629,32 @@ rb_mod_attr_accessor(int argc, VALUE *ar /* * call-seq: - * mod.const_get(sym) => obj + * mod.const_get(sym, inherit=true) => obj * * Returns the value of the named constant in mod. * * Math.const_get(:PI) #=> 3.14159265358979 + * + * If the constant is not defined or is defined by the ancestors and + * +inherit+ is false, +NameError+ will be raised. */ static VALUE -rb_mod_const_get(VALUE mod, VALUE name) +rb_mod_const_get(int argc, VALUE *argv, VALUE mod) { - ID id = rb_to_id(name); + VALUE name, recur; + ID id; + if (argc == 1) { + name = argv[0]; + recur = Qtrue; + } + else { + rb_scan_args(argc, argv, "11", &name, &recur); + } + id = rb_to_id(name); if (!rb_is_const_id(id)) { rb_name_error(id, "wrong constant name %s", rb_id2name(id)); } - return rb_const_get(mod, id); + return RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id); } @@ -1673,21 +1685,32 @@ rb_mod_const_set(VALUE mod, VALUE name, /* * call-seq: - * mod.const_defined?(sym) => true or false + * mod.const_defined?(sym, inherit=true) => true or false * * Returns true if a constant with the given name is - * defined by mod. + * defined by mod, or its ancestors if +inherit+ is not false. * * Math.const_defined? "PI" #=> true + * IO.const_defined? "SYNC" #=> true + * IO.const_defined? "SYNC", false #=> false */ static VALUE -rb_mod_const_defined(VALUE mod, VALUE name) +rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) { - ID id = rb_to_id(name); + VALUE name, recur; + ID id; + if (argc == 1) { + name = argv[0]; + recur = Qtrue; + } + else { + rb_scan_args(argc, argv, "11", &name, &recur); + } + id = rb_to_id(name); if (!rb_is_const_id(id)) { rb_name_error(id, "wrong constant name %s", rb_id2name(id)); } - return rb_const_defined_at(mod, id); + return RTEST(recur) ? rb_const_defined(mod, id) : rb_const_defined_at(mod, id); } @@ -2499,7 +2522,7 @@ Init_Object(void) rb_define_method(rb_cModule, "constants", rb_mod_constants, 0); /* in variable.c */ - rb_define_method(rb_cModule, "const_get", rb_mod_const_get, 1); + rb_define_method(rb_cModule, "const_get", rb_mod_const_get, -1); rb_define_method(rb_cModule, "const_set", rb_mod_const_set, 2); - rb_define_method(rb_cModule, "const_defined?", rb_mod_const_defined, 1); + rb_define_method(rb_cModule, "const_defined?", rb_mod_const_defined, -1); rb_define_private_method(rb_cModule, "remove_const", rb_mod_remove_const, 1); /* in variable.c */ -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦