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.
def gen_times(factor) return Proc.new {|n| n*factor } end times3 = gen_times(3) times5 = gen_times(5) times3.call(12) #=> 36 times5.call(5) #=> 25 times3.call(times5.call(4)) #=> 60
Creates a new Proc
object, bound to the current context.
Proc::new
may be called without a block only within a method
with an attached block, in which case that block is converted to the
Proc
object.
def proc_from Proc.new end proc = proc_from { "hello" } proc.call #=> "hello"
static VALUE proc_s_new(argc, argv, klass) int argc; VALUE *argv; VALUE klass; { VALUE block = proc_alloc(klass, Qfalse); rb_obj_call_init(block, argc, argv); return block; }
Return true
if prc is the same object as
other_proc, or if they are both procs with the same body.
static VALUE proc_eq(self, other) VALUE self, other; { struct BLOCK *data, *data2; if (self == other) return Qtrue; if (TYPE(other) != T_DATA) return Qfalse; if (RDATA(other)->dmark != (RUBY_DATA_FUNC)blk_mark) return Qfalse; if (CLASS_OF(self) != CLASS_OF(other)) return Qfalse; Data_Get_Struct(self, struct BLOCK, data); Data_Get_Struct(other, struct BLOCK, data2); if (data->body != data2->body) return Qfalse; if (data->var != data2->var) return Qfalse; if (data->scope != data2->scope) return Qfalse; if (data->dyna_vars != data2->dyna_vars) return Qfalse; if (data->flags != data2->flags) return Qfalse; return Qtrue; }
Invokes the block, setting the block's parameters to the values in params using something close to method calling semantics. Generates a warning if multiple values are passed to a proc that expects just one (previously this silently converted the parameters to an array).
For procs created using Kernel.proc
, generates an error if
the wrong number of parameters are passed to a proc with multiple
parameters. For procs created using Proc.new
, extra parameters
are silently discarded.
Returns the value of the last expression evaluated in the block. See also
Proc#yield
.
a_proc = Proc.new {|a, *b| b.collect {|i| i*a }} a_proc.call(9, 1, 2, 3) #=> [9, 18, 27] a_proc[9, 1, 2, 3] #=> [9, 18, 27] a_proc = Proc.new {|a,b| a} a_proc.call(1,2,3)
produces:
prog.rb:5: wrong number of arguments (3 for 2) (ArgumentError) from prog.rb:4:in `call' from prog.rb:5
static VALUE proc_call(proc, args) VALUE proc, args; /* OK */ { return proc_invoke(proc, args, Qundef, 0); }
Returns the number of arguments that would not be ignored. If the block is
declared to take no arguments, returns 0. If the block is known to take
exactly n arguments, returns n. If the block has optional arguments, return
-n-1, where n is the number of mandatory arguments. A proc
with no argument declarations is the same a block declaring ||
as its arguments.
Proc.new {}.arity #=> 0 Proc.new {||}.arity #=> 0 Proc.new {|a|}.arity #=> 1 Proc.new {|a,b|}.arity #=> 2 Proc.new {|a,b,c|}.arity #=> 3 Proc.new {|*a|}.arity #=> -1 Proc.new {|a,*b|}.arity #=> -2
static VALUE proc_arity(proc) VALUE proc; { struct BLOCK *data; NODE *list; int n; Data_Get_Struct(proc, struct BLOCK, data); if (data->var == 0) { if (data->body && nd_type(data->body) == NODE_IFUNC && data->body->nd_cfnc == bmcall) { return method_arity(data->body->nd_tval); } return INT2FIX(-1); } if (data->var == (NODE*)1) return INT2FIX(0); if (data->var == (NODE*)2) return INT2FIX(0); switch (nd_type(data->var)) { default: return INT2FIX(1); case NODE_MASGN: list = data->var->nd_head; n = 0; while (list) { n++; list = list->nd_next; } if (data->var->nd_args) return INT2FIX(-n-1); return INT2FIX(n); } }
Returns the binding associated with prc. Note that
Kernel#eval
accepts either a Proc
or a
Binding
object as its second parameter.
def fred(param) proc {} end b = fred(99) eval("param", b.binding) #=> 99 eval("param", b) #=> 99
static VALUE proc_binding(proc) VALUE proc; { struct BLOCK *orig, *data; VALUE bind; Data_Get_Struct(proc, struct BLOCK, orig); bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data); MEMCPY(data, orig, struct BLOCK, 1); frame_dup(&data->frame); if (data->iter) { blk_copy_prev(data); } else { data->prev = 0; } return bind; }
Invokes the block, setting the block's parameters to the values in params using something close to method calling semantics. Generates a warning if multiple values are passed to a proc that expects just one (previously this silently converted the parameters to an array).
For procs created using Kernel.proc
, generates an error if
the wrong number of parameters are passed to a proc with multiple
parameters. For procs created using Proc.new
, extra parameters
are silently discarded.
Returns the value of the last expression evaluated in the block. See also
Proc#yield
.
a_proc = Proc.new {|a, *b| b.collect {|i| i*a }} a_proc.call(9, 1, 2, 3) #=> [9, 18, 27] a_proc[9, 1, 2, 3] #=> [9, 18, 27] a_proc = Proc.new {|a,b| a} a_proc.call(1,2,3)
produces:
prog.rb:5: wrong number of arguments (3 for 2) (ArgumentError) from prog.rb:4:in `call' from prog.rb:5
static VALUE proc_call(proc, args) VALUE proc, args; /* OK */ { return proc_invoke(proc, args, Qundef, 0); }
MISSING: documentation
static VALUE proc_clone(self) VALUE self; { struct BLOCK *orig, *data; VALUE bind; Data_Get_Struct(self, struct BLOCK, orig); bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data); CLONESETUP(bind, self); blk_dup(data, orig); return bind; }
static VALUE proc_dup(self) VALUE self; { struct BLOCK *orig, *data; VALUE bind; int safe = proc_get_safe_level(self); Data_Get_Struct(self, struct BLOCK, orig); bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data); blk_dup(data, orig); if (safe > PROC_TMAX) safe = PROC_TMAX; FL_SET(bind, (safe << PROC_TSHIFT) & PROC_TMASK); return bind; }
Part of the protocol for converting objects to Proc
objects.
Instances of class Proc
simply return themselves.
static VALUE proc_to_self(self) VALUE self; { return self; }
Shows the unique identifier for this proc, along with an indication of where the proc was defined.
static VALUE proc_to_s(self) VALUE self; { struct BLOCK *data; NODE *node; char *cname = rb_obj_classname(self); const int w = (sizeof(VALUE) * CHAR_BIT) / 4; long len = strlen(cname)+6+w; /* 6:tags 16:addr */ VALUE str; Data_Get_Struct(self, struct BLOCK, data); if ((node = data->frame.node) || (node = data->body)) { len += strlen(node->nd_file) + 2 + (SIZEOF_LONG*CHAR_BIT-NODE_LSHIFT)/3; str = rb_str_new(0, len); snprintf(RSTRING(str)->ptr, len+1, "#<%s:0x%.*lx@%s:%d>", cname, w, (VALUE)data->body, node->nd_file, nd_line(node)); } else { str = rb_str_new(0, len); snprintf(RSTRING(str)->ptr, len+1, "#<%s:0x%.*lx>", cname, w, (VALUE)data->body); } RSTRING(str)->len = strlen(RSTRING(str)->ptr); if (OBJ_TAINTED(self)) OBJ_TAINT(str); return str; }