From: Nobuyoshi Nakada Date: 2008-12-09T02:24:15+09:00 Subject: [ruby-core:20430] Re: Array#to_proc Hi, At Mon, 8 Dec 2008 22:21:16 +0900, Florian Gilcher wrote in [ruby-core:20421]: > This might make sense for an Array of Symbols. But i've also seen use > of this > in other interpretations, like for chaining Arrays of procs. Other > uses could be > imagined. What about Symbol#call()? (1..3).collect(&:*.(2)) #=> [2, 4, 6] Index: string.c =================================================================== --- string.c (revision 20574) +++ string.c (working copy) @@ -6944,4 +6944,71 @@ sym_to_proc(VALUE sym) static VALUE +yield_call(VALUE dummy, VALUE proc, int argc, VALUE *argv) +{ + return rb_proc_call_with_block(proc, argc, argv, Qnil); +} + +static VALUE +sym_call_with_args(VALUE dummy, VALUE args, int argc, VALUE *argv) +{ + VALUE obj, sym, proc, *ptr = RARRAY_PTR(args); + long len = RARRAY_LEN(args); + volatile VALUE newargs; + ID id; + + if (argc < 1) { + rb_raise(rb_eArgError, "no receiver given"); + } + proc = ptr[--len]; + sym = ptr[--len]; + obj = *argv++; + if (!--argc) { + argc = len; + argv = ptr; + } + else if (len) { + VALUE *p; + newargs = rb_ary_tmp_new(argc + len); + rb_ary_store(newargs, argc + len - 1, Qnil); + p = RARRAY_PTR(newargs); + MEMCPY(p, argv, VALUE, argc); + MEMCPY(p + argc, ptr, VALUE, len); + argv = p; + argc += len; + } + id = SYM2ID(sym); + RB_GC_GUARD(args); + if (NIL_P(proc)) { + return rb_funcall3(obj, id, argc, argv); + } + else { + return rb_block_call(obj, id, argc, argv, yield_call, proc); + } +} + +/* + * call-seq: + * sym.call(*args) + * sym.(*args) + * + * Returns a _Proc_ object which respond to the given method by _sym_ with _args_. + * + * (1..3).collect(&:*.(2)) #=> [2, 4, 6] + */ + +static VALUE +sym_to_proc_with_args(int argc, VALUE *argv, VALUE sym) +{ + VALUE args, proc = 0; + if (rb_block_given_p()) proc = rb_block_proc(); + if (argc == 0 && !proc) return sym_to_proc(sym); + args = rb_ary_tmp_new(argc + 2); + rb_ary_store(args, argc + 1, proc); + MEMCPY(RARRAY_PTR(args), argv, VALUE, argc); + RARRAY_PTR(args)[argc] = sym; + return rb_proc_new(sym_call_with_args, args); +} + +static VALUE sym_succ(VALUE sym) { @@ -7214,4 +7281,5 @@ Init_String(void) rb_define_method(rb_cSymbol, "=~", sym_match, 1); + rb_define_method(rb_cSymbol, "call", sym_to_proc_with_args, -1); rb_define_method(rb_cSymbol, "[]", sym_aref, -1); rb_define_method(rb_cSymbol, "slice", sym_aref, -1); -- Nobu Nakada