Proposal: Module#method_adding


#1

e$B!!$5$5$@$G$9!%e(B

e$B!!:#!$e(Basakusa.rb
e$B$G<r$r0{$s$G$?$s$G$9$,!$e(BModule#method_adding e$B$H$+!$$=$&e(B
e$B$$$&%a%=%C%I$H$$$&$N$O$I$&$G$7$g$&$+!%e(B
e$B%a%=%C%I$,Dj5A$5$l$kD>A0$K8F$P$le(B
e$B$k%a%=%C%I$G$9!%e(B

e$B$d$j$?$$$3$H!'e(B
e$B!!Nc$($P!$e(Bfoo
e$B$H$$$&%a%=%C%I$N%!<%P!<%i%$%I$r$7$?$H$-$K!$e(Bold_foo e$B$N$h$&e(B
e$B$J8E$$%a%=%C%I$Ne(B alias
e$B$r<+F0E
$K:n$k$K$O$I$&$9$l$P!$$H$$$&OC$K$J$j$^$7e(B
e$B$?!%e(BModule#method_added
e$B$r;H$&$H$I$&$@$m$&!$$H;W$C$?$N$G$9$,!$$3$l$O$9$Ge(B
e$B$K%a%=%C%I$r>e=q$-$7$?8e$G$h$P$l$k$h$&$G$9!%e(B

e$B!!$H$$$&$3$H$G!$%a%=%C%I$rDj5A$9$kD>A0$K%U%C%/$9$k$?$a$N%a%=%C%I$H$7$Fe(B
Module#method_adding
e$B$H$$$&$N$r?7@_$9$k$N$O$I$&$@$m$&!$$H$$$&0F$,$G$^$7e(B
e$B$?!%$9$G$K!$$=$&$$$&$3$H$r$9$kJ}K!$,$"$l$P$$$$$s$G$9$,!$$J$1$l$P!$0l$D8!e(B
e$BF$$48!F$$$$?$@$1$J$$$G$7$g$&$+!%e(B


#2

e$B:XF#$H?=$7$^$9!#e(B

On Tue, 10 Feb 2009 21:50:53 +0900
SASADA Koichi removed_email_address@domain.invalid wrote:

e$B$d$j$?$$$3$H!'e(B
e$B!!Nc$($P!$e(Bfoo e$B$H$$$&%a%=%C%I$N%!<%P!<%i%$%I$r$7$?$H$-$K!$e(Bold_foo e$B$N$h$&e(B
e$B$J8E$$%a%=%C%I$Ne(B alias e$B$r<+F0E
$K:n$k$K$O$I$&$9$l$P!$$H$$$&OC$K$J$j$^$7e(B

old_fooe$B$H$$$&$h$&$Je(Baliase$B$r:n$kJ}K!$K$OLdBj$,$"$k$H;W$&$N$G!"$=$l$r?d>)$9$ke(B
e$B$h$&$JJ}8~$NJQ99$K$O<+J,$OH?BP$G$9!#e(B

http://d.hatena.ne.jp/rubikitch/20080504/1209835550
http://blog.jayfields.com/2008/04/alternatives-for-redefining-methods.html

e$B$?$H$($P$G$9$,!“e(Bfooe$B$H$$$&%a%=%C%I$,e(Bold_fooe$B$H$7$Fe(Baliase$B$5$l$?8e!“e(Bfooe$B$,%!<%P!<%i%$%Ie(B
e$B$5$l$?$H$7$^$9!#$=$Ne(Bfooe$B$r4^$`%9%/%j%W%H$,B>$N?M$K$bMxMQ$5$l!":FEY%
!<%P!<%i%$%I$5$l$?$H$-!“e(B
e$BF1$8$h$&$Ke(Bold_fooe$B$H$$$&L>A0$Ge(Baliase$B$,:n@.$5$l$J$$J]>Z$,$I$3$K$”$k$G$7$g$&$+!#e(B
old_e$B$H$$$&L>A0$rIU$1$k!”$H$$$&9T0Y$rJ#?t$N?M4V$,;W$$$D$/$N$O!”$h$/$"$j$=$&$J$3$H$G$9!#e(B

e$B$=$N$h$&$J;~$O!"L58B%k!<%W$K$J$C$F$7$^$$$^$9!#e(B


#3

e$B!!$5$5$@$G$9!%e(B

Tadashi S. wrote::

e$B$=$N$h$&$J;~$O!"L58B%k!<%W$K$J$C$F$7$^$$$^$9!#e(B

e$B!!$^$!!$C1=c$JNc$r=P$7$^$7$?$,!$B>$K$b%*!<%P!<%i%$%I$7$=$&$K$J$C$?$iNc30e(B
e$B$rH/@8$5$;$?$$!$$H$+!%e(B

e$B$=$l$3$=!$e(Bold_foo e$B$r:FEY:n$m$&$H$7$?$H$-$H$+!%e(B

e$B$"!$e(Balias e$B$G$b$A$c$s$He(B method_added

e$B$O8F$P$l$k$s$G$9$M!%e(B

e$B!!e(Bold_foo
e$B$K$D$$$F$O!$L>A0$N>WFM$7$J$5$=$&$JJ}K!$O9M$($l$P?’!9$"$k$h$&$Ke(B
e$B$b;W$$$^$9!%e(B

e$B!!e(Bold_foo
e$B$r0B0W$K:n$k$3$H$O$^$:$$$+$b$7$l$^$;$s$,!$Ds0F<+BN$OK<AE*$K$Oe(B
e$B$=$l$r=uD9$9$k$3$H$H$OL54X78$K;W$($^$9!%e(B

e$B=P$9Nc$r4V0c$($?$+$be(B


#4

e$B:XF#$G$9!#e(B

On Wed, 11 Feb 2009 03:32:41 +0900
SASADA Koichi removed_email_address@domain.invalid wrote:

e$B!!e(Bold_foo e$B$r0B0W$K:n$k$3$H$O$^$:$$$+$b$7$l$^$;$s$,!$Ds0F<+BN$OK<AE*$K$Oe(B
e$B$=$l$r=uD9$9$k$3$H$H$OL54X78$K;W$($^$9!%e(B

e$B$=$&$G$9$M!"$@$H$7$?$i<+J,$OH?BP$9$kF05!$,$J$$$N$G!"$h$$$H;W$$$^$9!#e(B

e$B$?$@$d$O$j!"e(B

e$B!!$^$!!$C1=c$JNc$r=P$7$^$7$?$,!$B>$K$b%*!<%P!<%i%$%I$7$=$&$K$J$C$?$iNc30e(B
e$B$rH/@8$5$;$?$$!$$H$+!%e(B

e$B$@$1$@$H$A$g$C$HM}M3$,<e$$5$$b$7$^$9!#=@Fp@-$,>e$,$k0lJ}$G!"9uKb=Q;U$N=;$_=h$re(B
e$B0l$DA}$d$7$F$7$^$&$@$1$N$h$&$J5$$b!#e(B(e$B$G$b!“LLGr$=$&$G$O$”$j$^$9e(B)

e$B<+J,$Oe(BOOPe$B$K>$7$/$J$$$N$G$h$/J,$+$i$J$$$N$G$9$,!"%!<%P!<%i%$%I$r@Q6KE$K6X;_$9$ke(B
e$B$Y$->u67$H$$$&$N$O!“7k9=B?$/$”$k$b$N$@$C$?$j!":G6aN.9T$C$?$j$7$F$$$k$N$G$7$g$&$+!#e(B

e$B!D!D$H$3$3$^$G=q$$$F!"K\J*$N%Q%A%b%s$3$H$J$+$@$5$s$Ne(B4e$BG/A0$NF|5-$r;W$$=P$7$^$7$?!#e(B
http://www.rubyist.net/~nobu/t/20051118.html


#5

e$B1J0f!wCNG=!%6e9)Bg$G$9!%e(B

From: SASADA Koichi removed_email_address@domain.invalid
Subject: [ruby-dev:37982] Re: proposal: Module#method_adding
Date: Fri, 13 Feb 2009 05:52:57 +0900
Message-ID: removed_email_address@domain.invalid

e$B!!$H$$$&$3$H$G!$%a%=%C%I$rDj5A$9$kD>A0$K%U%C%/$9$k$?$a$N%a%=%C%I$H$7$Fe(B

  • …ed e$B7O$N%U%C%/%a%=%C%I$K!$e(B…ing e$B7O$rIU$12C$($?$/$J$C$F$/$ke(B
    e$B7k9=$-$j$,$J$$!%e(Bhook e$B4X?tA4HL$re(B set_trace_func e$B$_$?$$$K$^$H$a$k!)e(B

  • singleton_*ed e$B$,$"$k%a%=%C%I$Oe(B *ed e$B$Ne(B rdoc e$B$,$J$$!%e(B

method_added e$B$re(B method_added(symbol, pre_method_obj,
new_method_obj)
e$B$H$9$k$H$$$&9M$($O%@%a$G$9$+$M!)e(B
e$B$=$&$9$l$P!$e(Bdefine_method
e$B$G5l$$Dj5A$rJL$N%a%=%C%IL>$GDj5A$7$?$j!$e(B
e$BE,Ev$Ke(B wrap e$B$7$F?75l?%$j$^$<$F8F$S=P$9$h$&$K$7$?$j$H$+$,e(B
e$B<+M3$K<BAu$G$-$=$&$K;W$$$^$9!%e(B
e$BJLL>Dj5A$O<+NO$G$d$k$N$G!$>WFM%A%’%C%/$b$=$N:]$K$G$-$k$G$7$g$&!%e(B

e$B%a%=%C%I$r=q$-49$($kA0$K8F$P$l$k$+8e$K8F$P$l$k$Y$-$+$K$h$C$F!$e(B
pre_method_obj e$B$He(B new_method_obj
e$B$H$N$$$:$l$+0lJ}$OITMW$+$b$7$l$^$;$s!%e(B
Thread e$B$H$NMm$$r9M$($k$H!$%a%=%C%I$rCV$-49$($i$l$F$7$^$&A0$Ke(B
e$B8F$P$l$k$b$N$,2?$+$OM
$7$$5$$,$7$^$9$M!%e(B


#6

e$B!!$5$5$@$G$9!%e(B

SASADA Koichi wrote::

e$B!!$H$$$&$3$H$G!$%a%=%C%I$rDj5A$9$kD>A0$K%U%C%/$9$k$?$a$N%a%=%C%I$H$7$Fe(B
Module#method_adding e$B$H$$$&$N$r?7@_$9$k$N$O$I$&$@$m$&!$$H$$$&0F$,$G$^$7e(B
e$B$?!%$9$G$K!$$=$&$$$&$3$H$r$9$kJ}K!$,$"$l$P$$$$$s$G$9$,!$$J$1$l$P!$0l$D8!e(B
e$BF$$48!F$$$$?$@$1$J$$$G$7$g$&$+!%e(B

e$B!!$J$s$H$J$/<BAu$7$F$$^$7$?!%$A$J$$K!$e(Bmethod_added e$B$Ne(B rdoc
e$B$,$J$+$C$?e(B
e$B$N$G!$e(Bsingleton_method_added e$B$r%3%T!<$7$FE,Ev$K=q$-$^$7$?!%e(B

e$B!!5$$E$$$?E@$Oe(B2e$BE@!%e(B

  • …ed e$B7O$N%U%C%/%a%=%C%I$K!$e(B…ing
    e$B7O$rIU$12C$($?$/$J$C$F$/$ke(B
    e$B7k9=$-$j$,$J$$!%e(Bhook e$B4X?tA4HL$re(B set_trace_func
    e$B$_$?$$$K$^$H$a$k!)e(B

  • singleton_*ed e$B$,$"$k%a%=%C%I$Oe(B *ed e$B$Ne(B rdoc e$B$,$J$$!%e(B

Index: object.c

— object.c (e$B%j%S%8%g%se(B 22272)
+++ object.c (e$B:n6H%3%T!<e(B)
@@ -523,6 +523,91 @@ rb_obj_tap(VALUE obj)
*/

/*

    • Document-method: method_adding
    • call-seq:
    • method_adding(symbol)
      
    • Invoked as a callback whenever a method (except singleton method)
    • is adding to the class.
    • This method is called before method adding process.
    • module Chatty
      
    •   def Chatty.method_adding(id)
      
    •     puts "adding: #{id}, respond_to?: #{method_defined? id}"
      
    •   end
      
    •   def Chatty.method_added(id)
      
    •     puts "added: #{id}, respond_to?: #{method_defined? id}"
      
    •   end
      
    •   def self.one()     end
      
    •   def two()          end
      
    •   def Chatty.three() end
      
    • end
      
    • produces:
    • adding: two, respond_to?: false
      
    • added: two, respond_to?: true
      
  • */

+/*

    • Document-method: method_added
    • call-seq:
    • method_added(symbol)
      
    • Invoked as a callback whenever a method (except singleton method)
    • is added to the class.
    • module Chatty
      
    •   def Chatty.singleton_method_added(id)
      
    •     puts "Adding #{id}"
      
    •   end
      
    •   def self.one()     end
      
    •   def two()          end
      
    •   def Chatty.three() end
      
    • end
      
    • produces:
    • Adding 2
      
  • */

+/*

    • Document-method: singleton_method_adding
    • call-seq:
    • singleton_method_adding(symbol)
      
    • Invoked as a callback whenever a singleton method is adding to the
    • receiver. This method is called before method added process.
    • module Chatty
      
    •   def Chatty.singleton_method_adding(id)
      
    •     puts "adding: #{id}, respond_to?: #{self.respond_to? id}"
      
    •   end
      
    •   def Chatty.singleton_method_added(id)
      
    •     puts "added: #{id}, respond_to?: #{self.respond_to? id}"
      
    •   end
      
    •   def self.one()     end
      
    •   def two()          end
      
    •   def Chatty.three() end
      
    • end
      
    • produces:
    • adding: singleton_method_added, respond_to?: false
      
    • added: singleton_method_added, respond_to?: true
      
    • adding: one, respond_to?: false
      
    • added: one, respond_to?: true
      
    • adding: three, respond_to?: false
      
    • added: three, respond_to?: true
      
  • */

+/*

  • Document-method: singleton_method_added
  • call-seq:
    @@ -533,7 +618,7 @@ rb_obj_tap(VALUE obj)
  • module Chatty
    
  •   def Chatty.singleton_method_added(id)
    
    •     puts "Adding #{id.id2name}"
      
    •     puts "Adding #{id}"
      
    •   end
      
    •   def self.one()     end
      
    •   def two()          end
      

@@ -2488,6 +2573,7 @@ Init_Object(void)
rb_define_method(rb_cBasicObject, “!=”, rb_obj_not_equal, 1);

 rb_define_private_method(rb_cBasicObject, "singleton_method_added",

rb_obj_dummy, 1);

  • rb_define_private_method(rb_cBasicObject,
    “singleton_method_adding”, rb_obj_dummy, 1);
    rb_define_private_method(rb_cBasicObject,
    “singleton_method_removed”, rb_obj_dummy, 1);
    rb_define_private_method(rb_cBasicObject,
    “singleton_method_undefined”, rb_obj_dummy, 1);

@@ -2497,6 +2583,7 @@ Init_Object(void)
rb_define_private_method(rb_cModule, “included”, rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, “extended”, rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, “method_added”, rb_obj_dummy,
1);

  • rb_define_private_method(rb_cModule, “method_adding”, rb_obj_dummy,
    1);
    rb_define_private_method(rb_cModule, “method_removed”,
    rb_obj_dummy, 1);
    rb_define_private_method(rb_cModule, “method_undefined”,
    rb_obj_dummy, 1);

Index: vm_method.c

— vm_method.c (e$B%j%S%8%g%se(B 22272)
+++ vm_method.c (e$B:n6H%3%T!<e(B)
@@ -10,7 +10,7 @@ static void rb_vm_check_redefinition_opt

static ID object_id;
static ID removed, singleton_removed, undefined, singleton_undefined;
-static ID added, singleton_added;
+static ID added, singleton_added, adding, singleton_adding;

struct cache_entry { /* method hash table. /
ID mid; /
method’s id */
@@ -125,6 +125,17 @@ rb_add_method(VALUE klass, ID mid, NODE
if (OBJ_FROZEN(klass)) {
rb_error_frozen(“class/module”);
}
+

  • if (node && mid != ID_ALLOCATOR && ruby_running) {

  • if (FL_TEST(klass, FL_SINGLETON)) {

  •  rb_funcall(rb_iv_get(klass, "__attached__"), singleton_adding, 1,
    
  •       ID2SYM(mid));
    
  • }

  • else {

  •  rb_funcall(klass, adding, 1, ID2SYM(mid));
    
  • }

  • }

  • rb_clear_cache_by_id(mid);

    /*
    @@ -749,6 +760,13 @@ rb_alias(VALUE klass, ID name, ID def)
    singleton = rb_iv_get(klass, “attached”);
    }

  • if (singleton) {

  • rb_funcall(singleton, singleton_adding, 1, ID2SYM(name));

  • }

  • else {

  • rb_funcall(klass, adding, 1, ID2SYM(name));

  • }

  • orig_fbody->nd_cnt++;

    if (st_lookup(RCLASS_M_TBL(klass), name, &data)) {
    @@ -1132,7 +1150,9 @@ Init_eval_method(void)

    object_id = rb_intern(“object_id”);
    added = rb_intern(“method_added”);

  • adding = rb_intern(“method_adding”);
    singleton_added = rb_intern(“singleton_method_added”);

  • singleton_adding = rb_intern(“singleton_method_adding”);
    removed = rb_intern(“method_removed”);
    singleton_removed = rb_intern(“singleton_method_removed”);
    undefined = rb_intern(“method_undefined”);


#7

e$B1J0f!wCNG=!%6e9)Bg$G$9!%e(B

From: Urabe S. removed_email_address@domain.invalid
Subject: [ruby-dev:37989] Re: proposal: Module#method_adding
Date: Fri, 13 Feb 2009 12:19:50 +0900
Message-ID: removed_email_address@domain.invalid

e$B%U%C%/$,8F$P$l$kEY$Ke(BMethode$B%*%V%8%’%/%H$r@8@.$9$k$H$$$&$N$,Cx$7$/Hs8zN(e(B
e$B$H$$$&OC$rJ9$-$^$9!#e(B
method_addede$B$,>/!9CY$$$/$i$$$,$I$&$7$?!"$H$$$&$N$b8+<1$N0l$D$H$O;W$$$^$9$,!#e(B

method_added e$B$,Dj5A$5$l$F$$$J$$8B$j$Oe(B
Method e$B%%V%8%’%/%H$O:n$i$J$/$F$b$$$$$G$9$h$M!%e(B
Method e$B$NM-L5$r3NG’$7$?8e$Ge(B Method
e$B%
%V%8%’%/%H$r:n$l$P$$$$$O$:$G$9!%e(B

method_added
e$B$NM-L5$rD4$Y$k%9%F%C%W$O$$$:$l$K$;$h0lEY$OI,MW$J$N$G!$e(B
e$B@h$KM-L5$rD4$Y$F$*$/$3$H<+BN$O%3%9%H%"%C%W$K$O$J$i$J$$$H;W$$$^$9!%e(B

method_added e$B$rK\Ev$K8F$V$3$H$O$5$[$IIQHK$K$O$J$$$G$7$g$&$+$i!$e(B
e$BK\Ev$K8F$VI,MW$,$"$k$H$-$K>/$7$/$i$$CY$/$F$bLdBj$O$J$$$G$7$g$&!%e(B

symbol e$B$@$1$r<u$1<h$ke(B method_adding/method_added
e$B$N>l9g$K$O!$e(B
method_adding e$B$G$ODj5A$5$l$kM=Dj$Ne(B method e$B$,F@$i$l$:!$e(B
method_added e$B$G$O:FDj5AA0$Ne(B method e$B$,F@$i$l$^$;$s!%e(B
method_adding/method_added
e$B$NN>J}$G$NA`:n$,I,MW$K$J$k$+$b$7$l$^$;$s!%e(B
e$B$=$N>l9g!$5le(B method e$B$Ne(B Method e$B%%V%8%’%/%H$re(B
method_adding e$B$+$ie(B method_added e$B$K0z$-$o$?$9$?$a$NJQ?t$be(B
e$BMQ0U$7$J$1$l$P$J$i$J$$$+$b$7$l$^$;$s!%e(B
e$B0l$D$N%a%=%C%I$GN>J}$Ne(B Method e$B%
%V%8%’%/%H$r<u$1<h$l$k$J$i!$e(B
e$B%f!<%6$O3Z$,$G$-$^$9!%e(B(^_^)

e$B$H$O$$$(!$e(Bmethod e$BDj5A;~$KFbIt$Ge(B
(1) hook e$B$NM-L5$r8!::e(B
(2) hook e$B$,B8:$7$?$J$i!$5l%a%=%C%I$Ne(B Method
e$B%*%V%8%’%/%H$r@8@.e(B
(3) method e$B$rDj5Ae(B
(4) hook e$B$,B8:
$7$?$J$i!$?7%a%=%C%I$Ne(B Method
e$B%*%V%8%’%/%H$r@8@.$7$Fe(B
hook e$B$N8F$S=P$7e(B
e$B$H$$$&%9%F%C%W$r7P$J$1$l$P$$$1$J$$$N$OLLE]$J$N$G!$e(B
method_adding e$B$He(B method_added
e$B$H$rAH$_9g$o$;$F$J$s$H$+$G$-$k$J$ie(B
e$B$=$l$G==J,$@$m$&$H$$$&<gD%$bM}2r$G$-$^$9!%e(B

e$B;d$Oe(B Method
e$B%*%V%8%’%/%H$r<u$1<h$l$kJ}$,4r$7$$$h$&$K;W$($^$9$,!$e(B
e$B!V$=$&$"$k$Y$-!W$H$^$G6/$/$O<gD%$7$^$;$s!%e(B
e$BH=CG$O$*G$$;$7$^$9!%e(B

…e$B$C$F!$L5@UG$e(B (^_^;


#8

Hidetoshi NAGAI e$B$5$s$O=q$-$^$7$?e(B:

method_added e$B$re(B method_added(symbol, pre_method_obj, new_method_obj)
e$B$H$9$k$H$$$&9M$($O%@%a$G$9$+$M!)e(B

e$B%U%C%/$,8F$P$l$kEY$Ke(BMethode$B%*%V%8%’%/%H$r@8@.$9$k$H$$$&$N$,Cx$7$/Hs8zN($H$$$&OCe(B
e$B$rJ9$-$^$9!#e(B
method_addede$B$,>/!9CY$$$/$i$$$,$I$&$7$?!"$H$$$&$N$b8+<1$N0l$D$H$O;W$$$^$9$,!#e(B