# 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

new {|...| block } → a_proc click to toggle source
new → a_proc

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

proc === obj → result_of_proc click to toggle source

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)
    {
        /* removed */
    }

prc[params,...] → obj click to toggle source

Invokes the block, setting the block's parameters to the values in params using something close to method calling semantics. Returns the value of the last expression evaluated in the block.

    a_proc = Proc.new {|scalar, *values| values.map {|value| value*scalar } }
    a_proc.call(9, 1, 2, 3)    #=> [9, 18, 27]
    a_proc[9, 1, 2, 3]         #=> [9, 18, 27]
    a_proc.(9, 1, 2, 3)        #=> [9, 18, 27]
    a_proc.yield(9, 1, 2, 3)   #=> [9, 18, 27]

Note that `prc.()` invokes `prc.call()` with the parameters given. It's syntactic sugar to hide “call”.

For procs created using `lambda` or `->()` an error is generated if the wrong number of parameters are passed to the proc. For procs created using `Proc.new` or `Kernel.proc`, extra parameters are silently discarded and missing parameters are set to `nil`.

    a_proc = proc {|a,b| [a,b] }
    a_proc.call(1)   #=> [1, nil]

    a_proc = lambda {|a,b| [a,b] }
    a_proc.call(1)   # ArgumentError: wrong number of arguments (given 1, expected 2)

See also #lambda?.

    static VALUE
    proc_call(int argc, VALUE *argv, VALUE procval)
    {
        /* removed */
    }

arity → integer click to toggle source

Returns the number of mandatory arguments. 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, returns -n-1, where n is the number of mandatory arguments, with the exception for blocks that are not lambdas and have only a finite number of optional arguments; in this latter case, returns n. Keyword arguments will be considered as a single additional argument, that argument being mandatory if any keyword argument is mandatory. A `proc` with no argument declarations is the same as 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:, y:, z:0| }.arity   #=>  1
    proc { |*a, x:, y:0| }.arity   #=> -2

    proc   { |a=0| }.arity         #=>  0
    lambda { |a=0| }.arity         #=> -1
    proc   { |a=0, b| }.arity      #=>  1
    lambda { |a=0, b| }.arity      #=> -2
    proc   { |a=0, b=0| }.arity    #=>  0
    lambda { |a=0, b=0| }.arity    #=> -1
    proc   { |a, b=0| }.arity      #=>  1
    lambda { |a, b=0| }.arity      #=> -2
    proc   { |(a, b), c=0| }.arity #=>  1
    lambda { |(a, b), c=0| }.arity #=> -2
    proc   { |a, x:0, y:0| }.arity #=>  1
    lambda { |a, x:0, y:0| }.arity #=> -2

    static VALUE
    proc_arity(VALUE self)
    {
        int arity = rb_proc_arity(self);
        return INT2FIX(arity);
    }

binding → binding click to toggle source

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)
    {
        VALUE bindval, binding_self = Qundef;
        rb_binding_t *bind;
        const rb_proc_t *proc;
        const rb_iseq_t *iseq = NULL;
        const struct rb_block *block;
        const rb_env_t *env = NULL;

        GetProcPtr(self, proc);
        block = &proc->block;

      again:
        switch (vm_block_type(block)) {
          case block_type_iseq:
            iseq = block->as.captured.code.iseq;
            binding_self = block->as.captured.self;
            env = VM_ENV_ENVVAL_PTR(block->as.captured.ep);
            break;
          case block_type_proc:
            GetProcPtr(block->as.proc, proc);
            block = &proc->block;
            goto again;
          case block_type_symbol:
            goto error;
          case block_type_ifunc:
            {
                const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
                if (IS_METHOD_PROC_IFUNC(ifunc)) {
                    VALUE method = (VALUE)ifunc->data;
                    binding_self = method_receiver(method);
                    iseq = rb_method_iseq(method);
                    env = VM_ENV_ENVVAL_PTR(block->as.captured.ep);
                    env = env_clone(env, method_cref(method));
                    /* set empty iseq */
                    RB_OBJ_WRITE(env, &env->iseq, rb_iseq_new(NULL, rb_str_new2("<empty iseq>"), rb_str_new2("<empty_iseq>"), Qnil, 0, ISEQ_TYPE_TOP));
                    break;
                }
                else {
                  error:
                    rb_raise(rb_eArgError, "Can't create Binding from C level Proc");
                    return Qnil;
                }
            }
        }

        bindval = rb_binding_alloc(rb_cBinding);
        GetBindingPtr(bindval, bind);
        RB_OBJ_WRITE(bindval, &bind->block.as.captured.self, binding_self);
        RB_OBJ_WRITE(bindval, &bind->block.as.captured.code.iseq, env->iseq);
        rb_vm_block_ep_update(bindval, &bind->block, env->ep);
        RB_OBJ_WRITTEN(bindval, Qundef, VM_ENV_ENVVAL(env->ep));

        if (iseq) {
            rb_iseq_check(iseq);
            RB_OBJ_WRITE(bindval, &bind->pathobj, iseq->body->location.pathobj);
            bind->first_lineno = FIX2INT(rb_iseq_first_lineno(iseq));
        }
        else {
            RB_OBJ_WRITE(bindval, &bind->pathobj,
                         rb_iseq_pathobj_new(rb_fstring_cstr("(binding)"), Qnil));
            bind->first_lineno = 1;
        }

        return bindval;
    }

call(params,...) → obj click to toggle source

Invokes the block, setting the block's parameters to the values in params using something close to method calling semantics. Returns the value of the last expression evaluated in the block.

    a_proc = Proc.new {|scalar, *values| values.map {|value| value*scalar } }
    a_proc.call(9, 1, 2, 3)    #=> [9, 18, 27]
    a_proc[9, 1, 2, 3]         #=> [9, 18, 27]
    a_proc.(9, 1, 2, 3)        #=> [9, 18, 27]
    a_proc.yield(9, 1, 2, 3)   #=> [9, 18, 27]

Note that `prc.()` invokes `prc.call()` with the parameters given. It's syntactic sugar to hide “call”.

For procs created using `lambda` or `->()` an error is generated if the wrong number of parameters are passed to the proc. For procs created using `Proc.new` or `Kernel.proc`, extra parameters are silently discarded and missing parameters are set to `nil`.

    a_proc = proc {|a,b| [a,b] }
    a_proc.call(1)   #=> [1, nil]

    a_proc = lambda {|a,b| [a,b] }
    a_proc.call(1)   # ArgumentError: wrong number of arguments (given 1, expected 2)

See also #lambda?.

    static VALUE
    proc_call(int argc, VALUE *argv, VALUE procval)
    {
        /* removed */
    }

curry → a_proc click to toggle source
curry(arity) → a_proc

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 (given 4, expected 3)
    p b.curry(5)                 #=> wrong number of arguments (given 5, expected 3)
    p b.curry(1)                 #=> wrong number of arguments (given 1, expected 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 (given 1, expected 3)

    b = proc { :foo }
    p b.curry[]                  #=> :foo

    static VALUE
    proc_curry(int argc, const 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);
    }

hash → integer click to toggle source

Returns a hash value corresponding to proc body.

See also Object#hash.

    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 ST2FIX(hash);
    }

inspect()
Alias for: to_s
lambda? → true or false click to toggle source

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 ensures 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;
    }

parameters → array click to toggle source

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;
        const rb_iseq_t *iseq = rb_proc_get_iseq(self, &is_proc);
        if (!iseq) {
            return unnamed_parameters(rb_proc_arity(self));
        }
        return rb_iseq_parameters(iseq, is_proc);
    }

source_location → [String, Integer] click to toggle source

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(rb_proc_get_iseq(self, 0));
    }

to_proc → proc click to toggle source

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;
    }

to_s → string click to toggle source

Returns the unique identifier for this proc, along with an indication of where the proc was defined.

    static VALUE
    proc_to_s(VALUE self)
    {
        const rb_proc_t *proc;
        GetProcPtr(self, proc);
        return rb_block_to_s(self, &proc->block, proc->is_lambda ? " (lambda)" : NULL);
    }

Also aliased as: inspect
yield(params,...) → obj click to toggle source

Invokes the block, setting the block's parameters to the values in params using something close to method calling semantics. Returns the value of the last expression evaluated in the block.

    a_proc = Proc.new {|scalar, *values| values.map {|value| value*scalar } }
    a_proc.call(9, 1, 2, 3)    #=> [9, 18, 27]
    a_proc[9, 1, 2, 3]         #=> [9, 18, 27]
    a_proc.(9, 1, 2, 3)        #=> [9, 18, 27]
    a_proc.yield(9, 1, 2, 3)   #=> [9, 18, 27]

Note that `prc.()` invokes `prc.call()` with the parameters given. It's syntactic sugar to hide “call”.

For procs created using `lambda` or `->()` an error is generated if the wrong number of parameters are passed to the proc. For procs created using `Proc.new` or `Kernel.proc`, extra parameters are silently discarded and missing parameters are set to `nil`.

    a_proc = proc {|a,b| [a,b] }
    a_proc.call(1)   #=> [1, nil]

    a_proc = lambda {|a,b| [a,b] }
    a_proc.call(1)   # ArgumentError: wrong number of arguments (given 1, expected 2)

See also #lambda?.

    static VALUE
    proc_call(int argc, VALUE *argv, VALUE procval)
    {
        /* removed */
    }