遠藤と申します。

http://subtech.g.hatena.ne.jp/cho45/20071119/1195420784
で提案されている Proc#curry を組み込むのはどうでしょうか。

proc {|x, y, z| x + y + z }.curry
が
proc {|x| proc {|y| proc {|z| x + y + z } } }
と同じ意味になります。

ski コンビネータを書くときなどに、ささやかな幸せが得られます。

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

逆に、Proc#curry の存在が害になることはないと思います。


以下はたたき台です。

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);
+}
+
+/*
  *  <code>Proc</code> 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);

-- 
Yusuke ENDOH <mame / tsg.ne.jp>