class Proc
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
Public Class Methods
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;
}
Public Instance Methods
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)
{
VALUE vret;
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;
}
}
vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
RB_GC_GUARD(procval);
return vret;
}
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)
{
VALUE vret;
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;
}
}
vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
RB_GC_GUARD(procval);
return vret;
}
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 {}.arity #=> 0 proc {||}.arity #=> 0 proc {|a|}.arity #=> 1 proc {|a,b|}.arity #=> 2 proc {|a,b,c|}.arity #=> 3 proc {|*a|}.arity #=> -1 proc {|a,*b|}.arity #=> -2 proc {|a,*b, c|}.arity #=> -3 proc { |x = 0| }.arity #=> 0 lambda { |a = 0| }.arity #=> -1 proc { |x=0, y| }.arity #=> 1 lambda { |x=0, y| }.arity #=> -2 proc { |x=0, y=0| }.arity #=> 0 lambda { |x=0, y=0| }.arity #=> -1 proc { |x, y=0| }.arity #=> 1 lambda { |x, y=0| }.arity #=> -2 proc { |(x, y), z=0| }.arity #=> 1 lambda { |(x, y), z=0| }.arity #=> -2
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 (RB_TYPE_P((VALUE)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 = rb_binding_alloc(rb_cBinding);
GetBindingPtr(bindval, bind);
bind->env = proc->envval;
bind->blockprocval = proc->blockprocval;
if (RUBY_VM_NORMAL_ISEQ_P(proc->block.iseq)) {
bind->path = proc->block.iseq->location.path;
bind->first_lineno = FIX2INT(rb_iseq_first_lineno(proc->block.iseq->self));
}
else {
bind->path = Qnil;
bind->first_lineno = 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)
{
VALUE vret;
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;
}
}
vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
RB_GC_GUARD(procval);
return vret;
}
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, max_arity, min_arity = rb_proc_min_max_arity(self, &max_arity);
VALUE arity;
rb_scan_args(argc, argv, "01", &arity);
if (NIL_P(arity)) {
arity = INT2FIX(min_arity);
}
else {
sarity = FIX2INT(arity);
if (rb_proc_lambda_p(self)) {
rb_check_arity(sarity, min_arity, max_arity);
}
}
return make_curry_proc(self, rb_ary_new(), arity);
}
Returns a hash value corresponding to proc body.
static VALUE
proc_hash(VALUE self)
{
st_index_t hash;
hash = rb_hash_start(0);
hash = rb_hash_proc(hash, self);
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 first_lineno = 0;
if (iseq->line_info_table) {
first_lineno = FIX2INT(rb_iseq_first_lineno(iseq->self));
}
str = rb_sprintf("#<%s:%p@%"PRIsVALUE":%d%s>", cname, (void *)self,
iseq->location.path, first_lineno, 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)
{
VALUE vret;
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;
}
}
vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
RB_GC_GUARD(procval);
return vret;
}