![show/hide quicksearch [+]](./images/find.png)
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, 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(VALUE self, VALUE other)
{
    if (self == other) {
        return Qtrue;
    }
    else {
        if (TYPE(other)          == T_DATA &&
            RDATA(other)->dmark  == proc_mark) {
            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 block's parameter. It is to allow a proc object to be a target of when clause in the 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;
    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 *proc;
            VALUE procval;
            procval = rb_block_proc();
            GetProcPtr(procval, proc);
            blockptr = &proc->block;
        }
    }
    return rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
                             argc, argv, blockptr);
}
             
            Invokes the block, with obj as the block's parameter. It is to allow a proc object to be a target of when clause in the 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;
    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 *proc;
            VALUE procval;
            procval = rb_block_proc();
            GetProcPtr(procval, proc);
            blockptr = &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)
{
    rb_proc_t *proc;
    rb_iseq_t *iseq;
    GetProcPtr(self, proc);
    iseq = proc->block.iseq;
    if (iseq) {
        if (BUILTIN_TYPE(iseq) != T_NODE) {
            if (iseq->arg_rest < 0) {
                return INT2FIX(iseq->argc);
            }
            else {
                return INT2FIX(-(iseq->argc + 1 + iseq->arg_post_len));
            }
        }
        else {
            NODE *node = (NODE *)iseq;
            if (nd_type(node) == NODE_IFUNC && node->nd_cfnc == bmcall) {
                /* method(:foo).to_proc.arity */
                return INT2FIX(method_arity(node->nd_tval));
            }
        }
    }
    return INT2FIX(-1);
}
             
            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 = binding_alloc(rb_cBinding);
    rb_binding_t *bind;
    GetProcPtr(self, proc);
    GetBindingPtr(bindval, bind);
    if (TYPE(proc->block.iseq) == T_NODE) {
        rb_raise(rb_eArgError, "Can't create Binding from C level Proc");
    }
    bind->env = proc->envval;
    return bindval;
}
             
            Invokes the block, with obj as the block's parameter. It is to allow a proc object to be a target of when clause in the 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;
    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 *proc;
            VALUE procval;
            procval = rb_block_proc();
            GetProcPtr(procval, proc);
            blockptr = &proc->block;
        }
    }
    return rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
                             argc, argv, blockptr);
}
             
             
               static VALUE
proc_clone(VALUE self)
{
    VALUE procval = proc_dup(self);
    CLONESETUP(procval, self);
    return procval;
}
             
            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 or 3) p b.curry(5) #=> wrong number of arguments (5 or 3) p b.curry(1) #=> wrong number of arguments (1 or 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 or 3) b = proc { :foo } p b.curry[] #=> :foo
 
               static VALUE
proc_curry(int argc, VALUE *argv, VALUE self)
{
    int sarity, marity = FIX2INT(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 (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);
}
             
             
               static VALUE
proc_dup(VALUE self)
{
    VALUE procval = rb_proc_alloc(rb_cProc);
    rb_proc_t *src, *dst;
    GetProcPtr(self, src);
    GetProcPtr(procval, dst);
    dst->block = src->block;
    dst->block.proc = procval;
    dst->envval = src->envval;
    dst->safe_level = src->safe_level;
    dst->is_lambda = src->is_lambda;
    return procval;
}
             
            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(VALUE self, VALUE other)
{
    if (self == other) {
        return Qtrue;
    }
    else {
        if (TYPE(other)          == T_DATA &&
            RDATA(other)->dmark  == proc_mark) {
            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;
}
             
            Return hash value corresponding to proc body.
 
               static VALUE
proc_hash(VALUE self)
{
    int hash;
    rb_proc_t *proc;
    GetProcPtr(self, proc);
    hash = (long)proc->block.iseq;
    hash ^= (long)proc->envval;
    hash ^= (long)proc->block.lfp >> 16;
    return INT2FIX(hash);
}
             
            Returns true for a Proc object which argument handling is rigid. Such procs are typically generated by lambda.
A Proc object generated by proc ignore extra arguments.
proc {|a,b| [a,b] }.call(1,2,3)    => [1,2]
It provides nil for lacked arguments.
proc {|a,b| [a,b] }.call(1)        => [1,nil]
It expand 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.
lambda {}.lambda?          => true
proc {}.lambda?            => false
::new is same as proc.
Proc.new {}.lambda?        => false
lambda, proc and ::new preserves 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 same as method definition. The defined method has no tricks.
class C
  define_method(:d) {}
end
C.new.e(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 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 is for a wrapper of define_method. It eases defining a method defining method which defines a usual method which has no tricks.
class << C
  def def2(name, &body)
    define_method(name, &body)
  end
end
class C
  def2(:f) {}
end
C.new.f(1,2)       => ArgumentError
The wrapper, def2, defines a method which has no tricks.
 
               static VALUE
proc_lambda_p(VALUE procval)
{
    rb_proc_t *proc;
    GetProcPtr(procval, proc);
    return proc->is_lambda ? Qtrue : Qfalse;
}
             
            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));
}
             
            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;
}
             
            Shows 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, with obj as the block's parameter. It is to allow a proc object to be a target of when clause in the 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;
    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 *proc;
            VALUE procval;
            procval = rb_block_proc();
            GetProcPtr(procval, proc);
            blockptr = &proc->block;
        }
    }
    return rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
                             argc, argv, blockptr);
}