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 rb_proc_s_new(int argc, VALUE *argv, VALUE klass) { VALUE block = proc_new(klass, FALSE); rb_obj_call_init(block, argc, argv); return block; }
Returns true
if prc is the same object as
other_proc, or if they are both procs with the same body.
static VALUE proc_eq(VALUE self, VALUE other) { if (self == other) { return Qtrue; } else { if (rb_obj_is_proc(other)) { rb_proc_t *p1, *p2; GetProcPtr(self, p1); GetProcPtr(other, p2); if (p1->envval == p2->envval && p1->block.iseq->iseq_size == p2->block.iseq->iseq_size && p1->block.iseq->local_size == p2->block.iseq->local_size && MEMCMP(p1->block.iseq->iseq, p2->block.iseq->iseq, VALUE, p1->block.iseq->iseq_size) == 0) { return Qtrue; } } } return Qfalse; }
Invokes the block with obj
as the proc's parameter like #call. It is to allow a proc object to
be a target of when
clause in a case statement.
static VALUE proc_call(int argc, VALUE *argv, VALUE procval) { rb_proc_t *proc; rb_block_t *blockptr = 0; rb_iseq_t *iseq; VALUE passed_procval; GetProcPtr(procval, proc); iseq = proc->block.iseq; if (BUILTIN_TYPE(iseq) == T_NODE || iseq->arg_block != -1) { if (rb_block_given_p()) { rb_proc_t *passed_proc; RB_GC_GUARD(passed_procval) = rb_block_proc(); GetProcPtr(passed_procval, passed_proc); blockptr = &passed_proc->block; } } return rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self, argc, argv, blockptr); }
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). Note that prc.() invokes prc.call() with the parameters given. It’s a syntax sugar to hide “call”.
For procs created using lambda
or ->()
an
error is generated if the wrong number of parameters are passed to a Proc with multiple parameters. For procs created
using Proc.new
or Kernel.proc
, 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 = lambda {|a,b| a} a_proc.call(1,2,3)
produces:
prog.rb:4:in `block in <main>': wrong number of arguments (3 for 2) (ArgumentError) from prog.rb:5:in `call' from prog.rb:5:in `<main>'
static VALUE proc_call(int argc, VALUE *argv, VALUE procval) { rb_proc_t *proc; rb_block_t *blockptr = 0; rb_iseq_t *iseq; VALUE passed_procval; GetProcPtr(procval, proc); iseq = proc->block.iseq; if (BUILTIN_TYPE(iseq) == T_NODE || iseq->arg_block != -1) { if (rb_block_given_p()) { rb_proc_t *passed_proc; RB_GC_GUARD(passed_procval) = rb_block_proc(); GetProcPtr(passed_procval, passed_proc); blockptr = &passed_proc->block; } } return rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self, argc, argv, blockptr); }
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 Proc.new {|a,*b, c|}.arity #=> -3
static VALUE proc_arity(VALUE self) { int arity = rb_proc_arity(self); return INT2FIX(arity); }
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
static VALUE proc_binding(VALUE self) { rb_proc_t *proc; VALUE bindval; rb_binding_t *bind; GetProcPtr(self, proc); if (TYPE(proc->block.iseq) == T_NODE) { if (!IS_METHOD_PROC_NODE((NODE *)proc->block.iseq)) { rb_raise(rb_eArgError, "Can't create Binding from C level Proc"); } } bindval = binding_alloc(rb_cBinding); GetBindingPtr(bindval, bind); bind->env = proc->envval; if (RUBY_VM_NORMAL_ISEQ_P(proc->block.iseq)) { bind->filename = proc->block.iseq->filename; bind->line_no = rb_iseq_first_lineno(proc->block.iseq); } else { bind->filename = Qnil; bind->line_no = 0; } return bindval; }
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). Note that prc.() invokes prc.call() with the parameters given. It’s a syntax sugar to hide “call”.
For procs created using lambda
or ->()
an
error is generated if the wrong number of parameters are passed to a Proc with multiple parameters. For procs created
using Proc.new
or Kernel.proc
, 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 = lambda {|a,b| a} a_proc.call(1,2,3)
produces:
prog.rb:4:in `block in <main>': wrong number of arguments (3 for 2) (ArgumentError) from prog.rb:5:in `call' from prog.rb:5:in `<main>'
static VALUE proc_call(int argc, VALUE *argv, VALUE procval) { rb_proc_t *proc; rb_block_t *blockptr = 0; rb_iseq_t *iseq; VALUE passed_procval; GetProcPtr(procval, proc); iseq = proc->block.iseq; if (BUILTIN_TYPE(iseq) == T_NODE || iseq->arg_block != -1) { if (rb_block_given_p()) { rb_proc_t *passed_proc; RB_GC_GUARD(passed_procval) = rb_block_proc(); GetProcPtr(passed_procval, passed_proc); blockptr = &passed_proc->block; } } return rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self, argc, argv, blockptr); }
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 for 3) p b.curry(5) #=> wrong number of arguments (5 for 3) p b.curry(1) #=> wrong number of arguments (1 for 3) 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 for 3) b = proc { :foo } p b.curry[] #=> :foo
static VALUE proc_curry(int argc, VALUE *argv, VALUE self) { int sarity, marity = rb_proc_arity(self); VALUE arity, opt = Qfalse; if (marity < 0) { marity = -marity - 1; opt = Qtrue; } rb_scan_args(argc, argv, "01", &arity); if (NIL_P(arity)) { arity = INT2FIX(marity); } else { sarity = FIX2INT(arity); if (rb_proc_lambda_p(self) && (sarity < marity || (sarity > marity && !opt))) { rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", sarity, marity); } } return make_curry_proc(self, rb_ary_new(), arity); }
Returns true
if prc is the same object as
other_proc, or if they are both procs with the same body.
static VALUE proc_eq(VALUE self, VALUE other) { if (self == other) { return Qtrue; } else { if (rb_obj_is_proc(other)) { rb_proc_t *p1, *p2; GetProcPtr(self, p1); GetProcPtr(other, p2); if (p1->envval == p2->envval && p1->block.iseq->iseq_size == p2->block.iseq->iseq_size && p1->block.iseq->local_size == p2->block.iseq->local_size && MEMCMP(p1->block.iseq->iseq, p2->block.iseq->iseq, VALUE, p1->block.iseq->iseq_size) == 0) { return Qtrue; } } } return Qfalse; }
Returns a hash value corresponding to proc body.
static VALUE proc_hash(VALUE self) { st_index_t hash; rb_proc_t *proc; GetProcPtr(self, proc); hash = rb_hash_start((st_index_t)proc->block.iseq); hash = rb_hash_uint(hash, (st_index_t)proc->envval); hash = rb_hash_uint(hash, (st_index_t)proc->block.lfp >> 16); hash = rb_hash_end(hash); return LONG2FIX(hash); }
Returns true
for a Proc object for
which argument handling is rigid. Such procs are typically generated by
lambda
.
A Proc object generated by proc
ignores extra arguments.
proc {|a,b| [a,b] }.call(1,2,3) #=> [1,2]
It provides nil
for missing arguments.
proc {|a,b| [a,b] }.call(1) #=> [1,nil]
It expands a single array argument.
proc {|a,b| [a,b] }.call([1,2]) #=> [1,2]
A Proc object generated by lambda
doesn’t have such tricks.
lambda {|a,b| [a,b] }.call(1,2,3) #=> ArgumentError lambda {|a,b| [a,b] }.call(1) #=> ArgumentError lambda {|a,b| [a,b] }.call([1,2]) #=> ArgumentError
#lambda? is a predicate for the
tricks. It returns true
if no tricks apply.
lambda {}.lambda? #=> true proc {}.lambda? #=> false
::new is the same as
proc
.
Proc.new {}.lambda? #=> false
lambda
, proc
and ::new preserve the tricks of a Proc object given by &
argument.
lambda(&lambda {}).lambda? #=> true proc(&lambda {}).lambda? #=> true Proc.new(&lambda {}).lambda? #=> true lambda(&proc {}).lambda? #=> false proc(&proc {}).lambda? #=> false Proc.new(&proc {}).lambda? #=> false
A Proc object generated by &
argument has the tricks
def n(&b) b.lambda? end n {} #=> false
The &
argument preserves the tricks if a Proc object is given by &
argument.
n(&lambda {}) #=> true n(&proc {}) #=> false n(&Proc.new {}) #=> false
A Proc object converted from a method has no tricks.
def m() end method(:m).to_proc.lambda? #=> true n(&method(:m)) #=> true n(&method(:m).to_proc) #=> true
define_method
is treated the same as method definition. The
defined method has no tricks.
class C define_method(:d) {} end C.new.d(1,2) #=> ArgumentError C.new.method(:d).to_proc.lambda? #=> true
define_method
always defines a method without the tricks, even
if a non-lambda Proc object is given. This is the
only exception for which the tricks are not preserved.
class C define_method(:e, &proc {}) end C.new.e(1,2) #=> ArgumentError C.new.method(:e).to_proc.lambda? #=> true
This exception insures that methods never have tricks and makes it easy to have wrappers to define methods that behave as usual.
class C def self.def2(name, &body) define_method(name, &body) end def2(:f) {} end C.new.f(1,2) #=> ArgumentError
The wrapper def2 defines a method which has no tricks.
VALUE rb_proc_lambda_p(VALUE procval) { rb_proc_t *proc; GetProcPtr(procval, proc); return proc->is_lambda ? Qtrue : Qfalse; }
Returns the parameter information of this proc.
prc = lambda{|x, y=42, *other|} prc.parameters #=> [[:req, :x], [:opt, :y], [:rest, :other]]
static VALUE rb_proc_parameters(VALUE self) { int is_proc; rb_iseq_t *iseq = get_proc_iseq(self, &is_proc); if (!iseq) { return unnamed_parameters(rb_proc_arity(self)); } return rb_iseq_parameters(iseq, is_proc); }
Returns the Ruby source filename and line number containing this proc or
nil
if this proc was not defined in Ruby (i.e. native)
VALUE rb_proc_location(VALUE self) { return iseq_location(get_proc_iseq(self, 0)); }
Part of the protocol for converting objects to Proc
objects.
Instances of class Proc
simply return themselves.
static VALUE proc_to_proc(VALUE self) { return self; }
Returns the unique identifier for this proc, along with an indication of where the proc was defined.
static VALUE proc_to_s(VALUE self) { VALUE str = 0; rb_proc_t *proc; const char *cname = rb_obj_classname(self); rb_iseq_t *iseq; const char *is_lambda; GetProcPtr(self, proc); iseq = proc->block.iseq; is_lambda = proc->is_lambda ? " (lambda)" : ""; if (RUBY_VM_NORMAL_ISEQ_P(iseq)) { int line_no = 0; if (iseq->insn_info_table) { line_no = rb_iseq_first_lineno(iseq); } str = rb_sprintf("#<%s:%p@%s:%d%s>", cname, (void *)self, RSTRING_PTR(iseq->filename), line_no, is_lambda); } else { str = rb_sprintf("#<%s:%p%s>", cname, (void *)proc->block.iseq, is_lambda); } if (OBJ_TAINTED(self)) { OBJ_TAINT(str); } return str; }
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). Note that prc.() invokes prc.call() with the parameters given. It’s a syntax sugar to hide “call”.
For procs created using lambda
or ->()
an
error is generated if the wrong number of parameters are passed to a Proc with multiple parameters. For procs created
using Proc.new
or Kernel.proc
, 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 = lambda {|a,b| a} a_proc.call(1,2,3)
produces:
prog.rb:4:in `block in <main>': wrong number of arguments (3 for 2) (ArgumentError) from prog.rb:5:in `call' from prog.rb:5:in `<main>'
static VALUE proc_call(int argc, VALUE *argv, VALUE procval) { rb_proc_t *proc; rb_block_t *blockptr = 0; rb_iseq_t *iseq; VALUE passed_procval; GetProcPtr(procval, proc); iseq = proc->block.iseq; if (BUILTIN_TYPE(iseq) == T_NODE || iseq->arg_block != -1) { if (rb_block_given_p()) { rb_proc_t *passed_proc; RB_GC_GUARD(passed_procval) = rb_block_proc(); GetProcPtr(passed_procval, passed_proc); blockptr = &passed_proc->block; } } return rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self, argc, argv, blockptr); }
Commenting is here to help enhance the documentation. For example, sample code, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.