Suggestion: Proc#curry

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

http://subtech.g.hatena.ne.jp/cho45/20071119/1195420784
e$B$GDs0F$5$l$F$$$ke(B Proc#curry e$B$rAH$_9~$`$N$O$I$&$G$7$g$&$+!#e(B

proc {|x, y, z| x + y + z }.curry
e$B$,e(B
proc {|x| proc {|y| proc {|z| x + y + z } } }
e$B$HF1$80UL#$K$J$j$^$9!#e(B

ski e$B%3%s%S%M!<%?$r=q$/$H$-$J$I$K!"$5$5$d$+$J9,$;$,F@$i$l$^$9!#e(B

s = proc {|f, g, x| f[x][g[x]] }.curry
k = proc {|x, y| x }.curry

e$B5U$K!"e(BProc#curry e$B$NB8:_$,32$K$J$k$3$H$O$J$$$H;W$$$^$9!#e(B

e$B0J2<$O$?$?$-Bf$G$9!#e(B

Index: proc.c

— proc.c (revision 15417)
+++ proc.c (working copy)
@@ -1608,7 +1608,60 @@
return bindval;
}

+static VALUE curry(VALUE dummy, VALUE args, int argc, VALUE *argv);
+
+static VALUE
+make_curry_proc(VALUE proc, VALUE passed, VALUE arity)
+{

  • VALUE args = rb_ary_new2(3);
  • RARRAY_PTR(args)[0] = proc;
  • RARRAY_PTR(args)[1] = passed;
  • RARRAY_PTR(args)[2] = arity;
  • rb_ary_freeze(args);
  • rb_ary_freeze(passed);
  • return rb_proc_new(curry, args);
    +}

+static VALUE
+curry(VALUE dummy, VALUE args, int argc, VALUE *argv)
+{

  • int i;
  • VALUE proc, passed, arity;
  • proc = RARRAY_PTR(args)[0];
  • passed = RARRAY_PTR(args)[1];
  • arity = RARRAY_PTR(args)[2];
  • passed = rb_ary_plus(passed, rb_ary_new4(argc, argv));
  • if(RARRAY_LEN(passed) < FIX2INT(arity)) {
  • return make_curry_proc(proc, passed, arity);
  • }
  • return rb_proc_call(proc, passed);
    +}

/*

    • call-seq:
    • prc.curry    => a_proc
      
    • Returns a curried proc.
    • x = proc {|a, b, c| a + b + c }
      
    • p x[1, 2, 3] #=> 6
      
    • x = x.curry
      
    • p x[1][2][3] #=> 6
      
  • */
    +static VALUE
    +proc_curry(VALUE self)
    +{
  • VALUE arity = proc_arity(self);
  • if(FIX2INT(arity) < 0) {
  • arity = INT2FIX(-FIX2INT(arity) - 1);
  • }
  • return make_curry_proc(self, rb_ary_new(), arity);
    +}

+/*

  • Proc objects are blocks of code that have been bound
    to
  • a set of local variables. Once bound, the code may be called in
  • different contexts and still access those variables.
    @@ -1646,6 +1699,7 @@
    rb_define_method(rb_cProc, “to_s”, proc_to_s, 0);
    rb_define_method(rb_cProc, “lambda?”, proc_lambda_p, 0);
    rb_define_method(rb_cProc, “binding”, proc_binding, 0);
  • rb_define_method(rb_cProc, “curry”, proc_curry, 0);

    /* Exceptions */
    rb_eLocalJumpError = rb_define_class(“LocalJumpError”,
    rb_eStandardError);

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:33676] Suggestion: Proc#curry”
on Sat, 9 Feb 2008 20:40:19 +0900, “Yusuke ENDOH” [email protected]
writes:

|はてなグループの終了日を2020年1月31日(金)に決定しました - はてなの告知
|e$B$GDs0F$5$l$F$$$ke(B Proc#curry e$B$rAH$_9~$`$N$O$I$&$G$7$g$&$+!#e(B
|
|proc {|x, y, z| x + y + z }.curry
|e$B$,e(B
|proc {|x| proc {|y| proc {|z| x + y + z } } }
|e$B$HF1$80UL#$K$J$j$^$9!#e(B

e$B$&!<$s!"%+%j!<2=$C$Fe(B

f = proc{|x, y, z| x + y + z }
f2 = f.curry(2)
f3 = f2.curry(3)
f3[4] # => 9

e$B$C$Fe(BAPIe$B$J$s$8$c$J$$$s$G$7$g$&$+!#$=$l$H$b$?$$$7$?0c$$$8$c$Je(B
e$B$$!)e(B

|e$B5U$K!"e(BProc#curry e$B$NB8:_$,32$K$J$k$3$H$O$J$$$H;W$$$^$9!#e(B

e$BL>A0$NE@$GG<F@$9$l$PF3F~$KH?BP$7$^$;$s!#e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:33701] Re: Suggestion: Proc#curry”
on Mon, 11 Feb 2008 23:53:59 +0900, “Yusuke ENDOH” [email protected]
writes:

|> e$B$&!<$s!“%+%j!<2=$C$Fe(B
|
|e$B%+%j!<2=$H$$$&$N$O!”!Ve(Bn e$B8D$N0z?t$rF1;~$K<u$1<h$C$F<B9T$9$k4X?t!W$r!"e(B
|e$B!V0z?t$re(B 1 e$B8D$:$De(B n e$B2s$N8F$S=P$7$KJ,$1$F<u$1<h$C$?8e$K<B9T$9$k4X?t!We(B
|e$B$KJQ$($k$3$H$G$9!#e(B
|e$B7?$G8@$&$J$ie(B (ae$B!_e(Bbe$B!_e(Bce$B!_e(Bd)->z e$B$J4X?t$+$ie(B a->b->c->d->z e$B$J4X?t$K$9$ke(B
|e$B$3$H$G$9!#e(B

e$B$=$&$J$s$@!#L5CN$rO*Dh$7$F$^$9$M!#e(B

|> f = proc{|x, y, z| x + y + z }
|> f2 = f.curry(2)
|> f3 = f2.curry(3)
|> f3[4] # => 9
|>
|> e$B$C$Fe(BAPIe$B$J$s$8$c$J$$$s$G$7$g$&$+!#$=$l$H$b$?$$$7$?0c$$$8$c$Je(B
|> e$B$$!)e(B
|
|e$B$3$l$O%+%j!<2=$G$O$J$/$FItJ,E,MQ$G$9$M!#$3$l$O$3$l$G0UL#$,$"$ke(B
|e$B$+$b$7$l$^$;$s!#e(B

e$B@$$NCf$K$O$3$&$$$&e(Bcurrye$B4X?t$,$"$U$l$F$^$9$M!#e(B

e$B$G!"G<F@$7$?$N$G%3%_%C%H$7$F$/$@$5$$!#e(B

e$B1sF#$G$9!#e(B

08/02/11 e$B$Ke(B Yukihiro M.[email protected]
e$B$5$s$O=q$-$^$7$?e(B:

|proc {|x| proc {|y| proc {|z| x + y + z } } }
|e$B$HF1$80UL#$K$J$j$^$9!#e(B

e$B$&!<$s!"%+%j!<2=$C$Fe(B

e$B%+%j!<2=$H$$$&$N$O!"!Ve(Bn
e$B8D$N0z?t$rF1;~$K<u$1<h$C$F<B9T$9$k4X?t!W$r!"e(B
e$B!V0z?t$re(B 1 e$B8D$:$De(B n
e$B2s$N8F$S=P$7$KJ,$1$F<u$1<h$C$?8e$K<B9T$9$k4X?t!We(B
e$B$KJQ$($k$3$H$G$9!#e(B
e$B7?$G8@$&$J$ie(B (ae$B!_e(Bbe$B!_e(Bce$B!_e(Bd)->z e$B$J4X?t$+$ie(B
a->b->c->d->z e$B$J4X?t$K$9$ke(B
e$B$3$H$G$9!#e(B

f = proc{|x, y, z| x + y + z }
f2 = f.curry(2)
f3 = f2.curry(3)
f3[4] # => 9

e$B$C$Fe(BAPIe$B$J$s$8$c$J$$$s$G$7$g$&$+!#$=$l$H$b$?$$$7$?0c$$$8$c$Je(B
e$B$$!)e(B

e$B$3$l$O%+%j!<2=$G$O$J$/$FItJ,E,MQ$G$9$M!#$3$l$O$3$l$G0UL#$,$"$ke(B
e$B$+$b$7$l$^$;$s!#e(B

e$B1sF#$G$9!#e(B

08/02/12 e$B$Ke(B Yukihiro M.[email protected]
e$B$5$s$O=q$-$^$7$?e(B:

e$B@$$NCf$K$O$3$&$$$&e(Bcurrye$B4X?t$,$"$U$l$F$^$9$M!#e(B

e$B$h$/$"$k8mMQ$_$?$$$G$9!#8mMQ$b9-$^$l$P@5MQ!)e(B
http://lambda-the-ultimate.org/node/2266

e$B$G!"G<F@$7$?$N$G%3%_%C%H$7$F$/$@$5$$!#e(B

e$B%3%_%C%H$7$^$7$?!#e(B
e$B2DJQD90z?t$I$&$9$k$H$+!"e(Blambda e$B$He(B proc
e$B$N0c$$$I$&$9$k$H$+!"e(B
e$B0z?te(B 0 e$B8D$N$H$-$I$&$9$k$H$+$O!"E,Ev$K7h$a$F$7$^$$$^$7$?!#e(B
e$B$^$:$+$C$?$iD>$7$^$9!#e(B

  • call-seq:
  • prc.curry         => a_proc
    
  • prc.curry(arity)  => a_proc
    
  • Returns a curried proc. If the optional arity argument is
    given,
  • it determines the number of arguments.
  • A curried proc receives some arguments. If a sufficient number of
  • arguments are supplied, it passes the supplied arguments to the
    original
  • proc and returns the result. Otherwise, returns another curried
    proc that
  • takes the rest of arguments.
  • b = proc {|x, y, z| (x||0) + (y||0) + (z||0) }
    
  • p b.curry[1][2][3]           #=> 6
    
  • p b.curry[1, 2][3, 4]        #=> 6
    
  • p b.curry(5)[1][2][3][4][5]  #=> 6
    
  • p b.curry(5)[1, 2][3, 4][5]  #=> 6
    
  • p b.curry(1)[1]              #=> 1
    
  • b = proc {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, 
    

&:+) }

  • p b.curry[1][2][3]           #=> 6
    
  • p b.curry[1, 2][3, 4]        #=> 10
    
  • p b.curry(5)[1][2][3][4][5]  #=> 15
    
  • p b.curry(5)[1, 2][3, 4][5]  #=> 15
    
  • p b.curry(1)[1]              #=> 1
    
  • b = lambda {|x, y, z| (x||0) + (y||0) + (z||0) }
    
  • p b.curry[1][2][3]           #=> 6
    
  • p b.curry[1, 2][3, 4]        #=> wrong number of arguments (4 or 
    
  • p b.curry(5)                 #=> wrong number of arguments (5 or 
    
  • p b.curry(1)                 #=> wrong number of arguments (1 or 
    
  • b = lambda {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, 
    

&:+) }

  • p b.curry[1][2][3]           #=> 6
    
  • p b.curry[1, 2][3, 4]        #=> 10
    
  • p b.curry(5)[1][2][3][4][5]  #=> 15
    
  • p b.curry(5)[1, 2][3, 4][5]  #=> 15
    
  • p b.curry(1)                 #=> wrong number of arguments (1 or 
    
  • b = proc { :foo }
    
  • p b.curry[]                  #=> :foo