class Proc - Documentation for Ruby 4.1
Description: class Proc: A +Proc+ object is an encapsulation of a block of code, which can be stored in a local variable, passed to a method or another Proc, and can be called
Keywords: ruby,class,Proc

🔍

No recent searches

# class Proc

A `Proc` object is an encapsulation of a block of code, which can be stored in a local variable, passed to a method or another `Proc`, and can be called. `Proc` is an essential concept in Ruby and a core of its functional programming features.

    square = Proc.new {|x| x**2 }

    square.call(3)  #=> 9
    # shorthands:
    square.(3)      #=> 9
    square[3]       #=> 9

`Proc` objects are closures, meaning they remember and can use the entire context in which they were created.

    def gen_times(factor)
      Proc.new {|n| n*factor } # remembers the value of factor at the moment of creation
    end

    times3 = gen_times(3)
    times5 = gen_times(5)

    times3.call(12)               #=> 36
    times5.call(5)                #=> 25
    times3.call(times5.call(4))   #=> 60

## Creation

There are several methods to create a `Proc`

- Use the `Proc` class constructor:

      proc1 = Proc.new {|x| x**2 }

- Use the `Kernel#proc` method as a shorthand of `Proc.new`:

      proc2 = proc {|x| x**2 }

- Receiving a block of code into proc argument (note the `&`):

      def make_proc(&block)
        block
      end

      proc3 = make_proc {|x| x**2 }

- Construct a proc with lambda semantics using the `Kernel#lambda` method (see below for explanations about lambdas):

      lambda1 = lambda {|x| x**2 }

- Use the Lambda proc literal syntax (also constructs a proc with lambda semantics):

      lambda2 = ->(x) { x**2 }

## Lambda and non-lambda semantics

Procs are coming in two flavors: lambda and non-lambda (regular procs). Differences are:

- In lambdas, `return` and `break` means exit from this lambda;

- In non-lambda procs, `return` means exit from embracing method (and will throw `LocalJumpError` if invoked outside the method);

- In non-lambda procs, `break` means exit from the method which the block given for. (and will throw `LocalJumpError` if invoked after the method returns);

- In lambdas, arguments are treated in the same way as in methods: strict, with `ArgumentError` for mismatching argument number, and no additional argument processing;

- Regular procs accept arguments more generously: missing arguments are filled with `nil`, single `Array` arguments are deconstructed if the proc has multiple arguments, and there is no error raised on extra arguments.

Examples:

    # +return+ in non-lambda proc, +b+, exits +m2+.
    # (The block +{ return }+ is given for +m1+ and embraced by +m2+.)
    $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { return }; $a << :m2 end; m2; p $a
    #=> []

    # +break+ in non-lambda proc, +b+, exits +m1+.
    # (The block +{ break }+ is given for +m1+ and embraced by +m2+.)
    $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { break }; $a << :m2 end; m2; p $a
    #=> [:m2]

    # +next+ in non-lambda proc, +b+, exits the block.
    # (The block +{ next }+ is given for +m1+ and embraced by +m2+.)
    $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { next }; $a << :m2 end; m2; p $a
    #=> [:m1, :m2]

    # Using +proc+ method changes the behavior as follows because
    # The block is given for +proc+ method and embraced by +m2+.
    $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { return }); $a << :m2 end; m2; p $a
    #=> []
    $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { break }); $a << :m2 end; m2; p $a
    # break from proc-closure (LocalJumpError)
    $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { next }); $a << :m2 end; m2; p $a
    #=> [:m1, :m2]

    # +return+, +break+ and +next+ in the stubby lambda exits the block.
    # (+lambda+ method behaves same.)
    # (The block is given for stubby lambda syntax and embraced by +m2+.)
    $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { return }); $a << :m2 end; m2; p $a
    #=> [:m1, :m2]
    $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { break }); $a << :m2 end; m2; p $a
    #=> [:m1, :m2]
    $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { next }); $a << :m2 end; m2; p $a
    #=> [:m1, :m2]

    p = proc {|x, y| "x=#{x}, y=#{y}" }
    p.call(1, 2)      #=> "x=1, y=2"
    p.call([1, 2])    #=> "x=1, y=2", array deconstructed
    p.call(1, 2, 8)   #=> "x=1, y=2", extra argument discarded
    p.call(1)         #=> "x=1, y=", nil substituted instead of error

    l = lambda {|x, y| "x=#{x}, y=#{y}" }
    l.call(1, 2)      #=> "x=1, y=2"
    l.call([1, 2])    # ArgumentError: wrong number of arguments (given 1, expected 2)
    l.call(1, 2, 8)   # ArgumentError: wrong number of arguments (given 3, expected 2)
    l.call(1)         # ArgumentError: wrong number of arguments (given 1, expected 2)

    def test_return
      -> { return 3 }.call      # just returns from lambda into method body
      proc { return 4 }.call    # returns from method
      return 5
    end

    test_return # => 4, return from proc

Lambdas are useful as self-sufficient functions, in particular useful as arguments to higher-order functions, behaving exactly like Ruby methods.

Procs are useful for implementing iterators:

    def test
      [[1, 2], [3, 4], [5, 6]].map {|a, b| return a if a + b > 10 }
                                #  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    end

Inside `map`, the block of code is treated as a regular (non-lambda) proc, which means that the internal arrays will be deconstructed to pairs of arguments, and `return` will exit from the method `test`. That would not be possible with a stricter lambda.

You can tell a lambda from a regular proc by using the `lambda?` instance method.

Lambda semantics is typically preserved during the proc lifetime, including `&`-deconstruction to a block of code:

    p = proc {|x, y| x }
    l = lambda {|x, y| x }
    [[1, 2], [3, 4]].map(&p) #=> [1, 3]
    [[1, 2], [3, 4]].map(&l) # ArgumentError: wrong number of arguments (given 1, expected 2)

The only exception is dynamic method definition: even if defined by passing a non-lambda proc, methods still have normal semantics of argument checking.

    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 unusual argument passing conventions, and makes it easy to have wrappers defining 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` receives body as a non-lambda proc, yet defines a method which has normal semantics.

## Conversion of other objects to procs

Any object that implements the `to_proc` method can be converted into a proc by the `&` operator, and therefore can be consumed by iterators.

    class Greeter
      def initialize(greeting)
        @greeting = greeting
      end

      def to_proc
        proc {|name| "#{@greeting}, #{name}!" }
      end
    end

    hi = Greeter.new("Hi")
    hey = Greeter.new("Hey")
    ["Bob", "Jane"].map(&hi)    #=> ["Hi, Bob!", "Hi, Jane!"]
    ["Bob", "Jane"].map(&hey)   #=> ["Hey, Bob!", "Hey, Jane!"]

Of the Ruby core classes, this method is implemented by `Symbol`, `Method`, and `Hash`.

    :to_s.to_proc.call(1)           #=> "1"
    [1, 2].map(&:to_s)              #=> ["1", "2"]

    method(:puts).to_proc.call(1)   # prints 1
    [1, 2].each(&method(:puts))     # prints 1, 2

    {test: 1}.to_proc.call(:test)       #=> 1
    %i[test many keys].map(&{test: 1})  #=> [1, nil, nil]

## Orphaned `Proc`

`return` and `break` in a block exit a method. If a `Proc` object is generated from the block and the `Proc` object survives until the method is returned, `return` and `break` cannot work. In such case, `return` and `break` raises `LocalJumpError`. A `Proc` object in such situation is called as orphaned `Proc` object.

Note that the method to exit is different for `return` and `break`. There is a situation that orphaned for `break` but not orphaned for `return`.

    def m1(&b) b.call end; def m2(); m1 { return } end; m2 # ok
    def m1(&b) b.call end; def m2(); m1 { break } end; m2 # ok

    def m1(&b) b end; def m2(); m1 { return }.call end; m2 # ok
    def m1(&b) b end; def m2(); m1 { break }.call end; m2 # LocalJumpError

    def m1(&b) b end; def m2(); m1 { return } end; m2.call # LocalJumpError
    def m1(&b) b end; def m2(); m1 { break } end; m2.call # LocalJumpError

Since `return` and `break` exits the block itself in lambdas, lambdas cannot be orphaned.

## Anonymous block parameters

To simplify writing short blocks, Ruby provides two different types of anonymous parameters: `it` (single parameter) and numbered ones: `_1`, `_2` and so on.

    # Explicit parameter:
    %w[test me please].each { |str| puts str.upcase } # prints TEST, ME, PLEASE
    (1..5).map { |i| i**2 } # => [1, 4, 9, 16, 25]

    # it:
    %w[test me please].each { puts it.upcase } # prints TEST, ME, PLEASE
    (1..5).map { it**2 } # => [1, 4, 9, 16, 25]

    # Numbered parameter:
    %w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE
    (1..5).map { _1**2 } # => [1, 4, 9, 16, 25]

### `it`

`it` is a name that is available inside a block when no explicit parameters defined, as shown above.

    %w[test me please].each { puts it.upcase } # prints TEST, ME, PLEASE
    (1..5).map { it**2 } # => [1, 4, 9, 16, 25]

`it` is a “soft keyword”: it is not a reserved name, and can be used as a name for methods and local variables:

    it = 5 # no warnings
    def it(&block) # RSpec-like API, no warnings
       # ...
    end

`it` can be used as a local variable even in blocks that use it as an implicit parameter (though this style is obviously confusing):

    [1, 2, 3].each {
      # takes a value of implicit parameter "it" and uses it to
      # define a local variable with the same name
      it = it**2
      p it
    }

In a block with explicit parameters defined `it` usage raises an exception:

    [1, 2, 3].each { |x| p it }
    # syntax error found (SyntaxError)
    # [1, 2, 3].each { |x| p it }
    #                        ^~ 'it' is not allowed when an ordinary parameter is defined

But if a local name (variable or method) is available, it would be used:

    it = 5
    [1, 2, 3].each { |x| p it }
    # Prints 5, 5, 5

Blocks using `it` can be nested:

    %w[test me].each { it.each_char { p it } }
    # Prints "t", "e", "s", "t", "m", "e"

Blocks using `it` are considered to have one parameter:

    p = proc { it**2 }
    l = lambda { it**2 }
    p.parameters     # => [[:opt]]
    p.arity          # => 1
    l.parameters     # => [[:req]]
    l.arity          # => 1

### Numbered parameters

Numbered parameters are another way to name block parameters implicitly. Unlike `it`, numbered parameters allow to refer to several parameters in one block.

    %w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE
    {a: 100, b: 200}.map { "#{_1} = #{_2}" } # => "a = 100", "b = 200"

Parameter names from `_1` to `_9` are supported:

    [10, 20, 30].zip([40, 50, 60], [70, 80, 90]).map { _1 + _2 + _3 }
    # => [120, 150, 180]

Though, it is advised to resort to them wisely, probably limiting yourself to `_1` and `_2`, and to one-line blocks.

Numbered parameters can’t be used together with explicitly named ones:

    [10, 20, 30].map { |x| _1**2 }
    # SyntaxError (ordinary parameter is defined)

Numbered parameters can’t be mixed with `it` either:

    [10, 20, 30].map { _1 + it }
    # SyntaxError: 'it' is not allowed when a numbered parameter is already used

To avoid conflicts, naming local variables or method arguments `_1`, `_2` and so on, causes an error.

      _1 = 'test'
    # ^~ _1 is reserved for numbered parameters (SyntaxError)

Using implicit numbered parameters affects block’s arity:

    p = proc { _1 + _2 }
    l = lambda { _1 + _2 }
    p.parameters     # => [[:opt, :_1], [:opt, :_2]]
    p.arity          # => 2
    l.parameters     # => [[:req, :_1], [:req, :_2]]
    l.arity          # => 2

Blocks with numbered parameters can’t be nested:

    %w[test me].each { _1.each_char { p _1 } }
    # numbered parameter is already used in outer block (SyntaxError)
    # %w[test me].each { _1.each_char { p _1 } }
    #                    ^~

### Public Class Methods

new {|...| block } → a_proc
Source

    static VALUE
    rb_proc_s_new(int argc, VALUE *argv, VALUE klass)
    {
        VALUE block = proc_new(klass, FALSE);

        rb_obj_call_init_kw(block, argc, argv, RB_PASS_CALLED_KEYWORDS);
        return block;
    }

Creates a new `Proc` object, bound to the current context.

    proc = Proc.new { "hello" }
    proc.call   #=> "hello"

Raises `ArgumentError` if called without a block.

    Proc.new    #=> ArgumentError

### Public Instance Methods

prc << g → a_proc
Source

    static VALUE
    proc_compose_to_left(VALUE self, VALUE g)
    {
        return rb_proc_compose_to_left(self, to_callable(g));
    }

Returns a proc that is the composition of this proc and the given g. The returned proc takes a variable number of arguments, calls g with them then calls this proc with the result.

    f = proc {|x| x * x }
    g = proc {|x| x + x }
    p (f << g).call(2) #=> 16

See `Proc#>>` for detailed explanations.

self == other → true or false
Source

    static VALUE
    proc_eq(VALUE self, VALUE other)
    {
        const rb_proc_t *self_proc, *other_proc;
        const struct rb_block *self_block, *other_block;

        if (rb_obj_class(self) !=  rb_obj_class(other)) {
            return Qfalse;
        }

        GetProcPtr(self, self_proc);
        GetProcPtr(other, other_proc);

        if (self_proc->is_from_method != other_proc->is_from_method ||
                self_proc->is_lambda != other_proc->is_lambda) {
            return Qfalse;
        }

        self_block = &self_proc->block;
        other_block = &other_proc->block;

        if (vm_block_type(self_block) != vm_block_type(other_block)) {
            return Qfalse;
        }

        switch (vm_block_type(self_block)) {
          case block_type_iseq:
            if (self_block->as.captured.ep != \
                    other_block->as.captured.ep ||
                    self_block->as.captured.code.iseq != \
                    other_block->as.captured.code.iseq) {
                return Qfalse;
            }
            break;
          case block_type_ifunc:
            if (self_block->as.captured.code.ifunc != \
                    other_block->as.captured.code.ifunc) {
                return Qfalse;
            }

            if (memcmp(
                    ((cfunc_proc_t *)self_proc)->env,
                    ((cfunc_proc_t *)other_proc)->env,
                    sizeof(((cfunc_proc_t *)self_proc)->env))) {
                return Qfalse;
            }
            break;
          case block_type_proc:
            if (self_block->as.proc != other_block->as.proc) {
                return Qfalse;
            }
            break;
          case block_type_symbol:
            if (self_block->as.symbol != other_block->as.symbol) {
                return Qfalse;
            }
            break;
        }

        return Qtrue;
    }

Returns whether `self` and `other` were created from the same code block:

    def return_block(&block)
      block
    end

    def pass_block_twice(&block)
      [return_block(&block), return_block(&block)]
    end

    block1, block2 = pass_block_twice { puts 'test' }
    # Blocks might be instantiated into Proc's lazily, so they may, or may not,
    # be the same object.
    # But they are produced from the same code block, so they are equal
    block1 == block2
    #=> true

    # Another Proc will never be equal, even if the code is the "same"
    block1 == proc { puts 'test' }
    #=> false

Also aliased as: eql?
===
Alias for: call
prc >> g → a_proc
Source

    static VALUE
    proc_compose_to_right(VALUE self, VALUE g)
    {
        return rb_proc_compose_to_right(self, to_callable(g));
    }

Returns a proc that is the composition of this proc and the given g. The returned proc takes a variable number of arguments, calls this proc with them then calls g with the result.

    f = proc {|x| x * x }
    g = proc {|x| x + x }
    p (f >> g).call(2) #=> 8

g could be other `Proc`, or Method, or any other object responding to `call` method:

    class Parser
      def self.call(text)
         # ...some complicated parsing logic...
      end
    end

    pipeline = File.method(:read) >> Parser >> proc { |data| puts "data size: #{data.count}" }
    pipeline.call('data.json')

See also `Method#>>` and `Method#<<`.

self[...] → obj

Invokes the block, setting the block’s parameters to the arguments 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 `Proc#lambda?`.

Alias for: call
arity → integer
Source

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

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

binding → binding
Source

    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;

        if (proc->is_isolated) rb_raise(rb_eArgError, "Can't create Binding from isolated Proc");

      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_ifunc:
            {
                const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
                if (IS_METHOD_PROC_IFUNC(ifunc)) {
                    VALUE method = (VALUE)ifunc->data;
                    VALUE name = rb_fstring_lit("<empty_iseq>");
                    rb_iseq_t *empty;
                    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 */
                    empty = rb_iseq_new(Qnil, name, name, Qnil, 0, ISEQ_TYPE_TOP);
                    RB_OBJ_WRITE(env, &env->iseq, empty);
                    break;
                }
            }
            /* FALLTHROUGH */
          case block_type_symbol:
            rb_raise(rb_eArgError, "Can't create Binding from C level Proc");
            UNREACHABLE_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(iseq)->location.pathobj);
            bind->first_lineno = ISEQ_BODY(iseq)->location.first_lineno;
        }
        else {
            RB_OBJ_WRITE(bindval, &bind->pathobj,
                         rb_iseq_pathobj_new(rb_fstring_lit("(binding)"), Qnil));
            bind->first_lineno = 1;
        }

        return bindval;
    }

Returns the binding associated with prc.

    def fred(param)
      proc {}
    end

    b = fred(99)
    eval("param", b.binding)   #=> 99

call(...) → obj
Source

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

Invokes the block, setting the block’s parameters to the arguments 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 `Proc#lambda?`.

Also aliased as: [], ===, yield
curry → a_proc
curry(arity) → a_proc
Source

    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;

        if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(arity = argv[0])) {
            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 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.

The optional arity argument should be supplied when currying procs with variable arguments to determine how many arguments are needed before the proc is called.

    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

eql?(other) → true or false

Returns whether `self` and `other` were created from the same code block:

    def return_block(&block)
      block
    end

    def pass_block_twice(&block)
      [return_block(&block), return_block(&block)]
    end

    block1, block2 = pass_block_twice { puts 'test' }
    # Blocks might be instantiated into Proc's lazily, so they may, or may not,
    # be the same object.
    # But they are produced from the same code block, so they are equal
    block1 == block2
    #=> true

    # Another Proc will never be equal, even if the code is the "same"
    block1 == proc { puts 'test' }
    #=> false

Alias for: ==
hash → integer
Source

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

Returns a hash value corresponding to proc body.

See also `Object#hash`.

inspect
Alias for: to_s
lambda? → true or false
Source

    VALUE
    rb_proc_lambda_p(VALUE procval)
    {
        rb_proc_t *proc;
        GetProcPtr(procval, proc);

        return RBOOL(proc->is_lambda);
    }

Returns `true` if a `Proc` object is lambda. `false` if non-lambda.

The lambda-ness affects argument handling and the behavior of `return` and `break`.

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

`Proc#lambda?` is a predicate for the tricks. It returns `true` if no tricks apply.

    lambda {}.lambda?            #=> true
    proc {}.lambda?              #=> false

`Proc.new` is the same as `proc`.

    Proc.new {}.lambda?          #=> false

`lambda`, `proc` and `Proc.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.

parameters(lambda: nil) → array
Source

    static VALUE
    rb_proc_parameters(int argc, VALUE *argv, VALUE self)
    {
        static ID keyword_ids[1];
        VALUE opt, lambda;
        VALUE kwargs[1];
        int is_proc ;
        const rb_iseq_t *iseq;

        iseq = rb_proc_get_iseq(self, &is_proc);

        if (!keyword_ids[0]) {
            CONST_ID(keyword_ids[0], "lambda");
        }

        rb_scan_args(argc, argv, "0:", &opt);
        if (!NIL_P(opt)) {
            rb_get_kwargs(opt, keyword_ids, 0, 1, kwargs);
            lambda = kwargs[0];
            if (!NIL_P(lambda)) {
                is_proc = !RTEST(lambda);
            }
        }

        if (!iseq) {
            return rb_unnamed_parameters(rb_proc_arity(self));
        }
        return rb_iseq_parameters(iseq, is_proc);
    }

Returns the parameter information of this proc. If the lambda keyword is provided and not nil, treats the proc as a lambda if true and as a non-lambda if false.

    prc = proc{|x, y=42, *other|}
    prc.parameters  #=> [[:opt, :x], [:opt, :y], [:rest, :other]]
    prc = lambda{|x, y=42, *other|}
    prc.parameters  #=> [[:req, :x], [:opt, :y], [:rest, :other]]
    prc = proc{|x, y=42, *other|}
    prc.parameters(lambda: true)  #=> [[:req, :x], [:opt, :y], [:rest, :other]]
    prc = lambda{|x, y=42, *other|}
    prc.parameters(lambda: false) #=> [[:opt, :x], [:opt, :y], [:rest, :other]]

ruby2_keywords → proc
Source

    static VALUE
    proc_ruby2_keywords(VALUE procval)
    {
        rb_proc_t *proc;
        GetProcPtr(procval, proc);

        rb_check_frozen(procval);

        if (proc->is_from_method) {
                rb_warn("Skipping set of ruby2_keywords flag for proc (proc created from method)");
                return procval;
        }

        switch (proc->block.type) {
          case block_type_iseq:
            if (ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_rest &&
                    !ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_post &&
                    !ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_kw &&
                    !ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_kwrest) {
                ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.ruby2_keywords = 1;
            }
            else {
                rb_warn("Skipping set of ruby2_keywords flag for proc (proc accepts keywords or post arguments or proc does not accept argument splat)");
            }
            break;
          default:
            rb_warn("Skipping set of ruby2_keywords flag for proc (proc not defined in Ruby)");
            break;
        }

        return procval;
    }

Marks the proc as passing keywords through a normal argument splat. This should only be called on procs that accept an argument splat (`*args`) but not explicit keywords or a keyword splat. It marks the proc such that if the proc is called with keyword arguments, the final hash argument is marked with a special flag such that if it is the final element of a normal argument splat to another method call, and that method call does not include explicit keywords or a keyword splat, the final element is interpreted as keywords. In other words, keywords will be passed through the proc to other methods.

This should only be used for procs that delegate keywords to another method, and only for backwards compatibility with Ruby versions before 2.7.

This method will probably be removed at some point, as it exists only for backwards compatibility. As it does not exist in Ruby versions before 2.7, check that the proc responds to this method before calling it. Also, be aware that if this method is removed, the behavior of the proc will change so that it does not pass through keywords.

    module Mod
      foo = ->(meth, *args, &block) do
        send(:"do_#{meth}", *args, &block)
      end
      foo.ruby2_keywords if foo.respond_to?(:ruby2_keywords)
    end

source_location → [String, Integer]
Source

    VALUE
    rb_proc_location(VALUE self)
    {
        return iseq_location(rb_proc_get_iseq(self, 0));
    }

Returns the Ruby source filename and line number containing this proc or `nil` if this proc was not defined in Ruby (i.e. native).

to_proc → proc
Source

    static VALUE
    proc_to_proc(VALUE self)
    {
        return self;
    }

Part of the protocol for converting objects to `Proc` objects. Instances of class `Proc` simply return themselves.

to_s → string
Source

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

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

Also aliased as: inspect
yield(...) → obj

Invokes the block, setting the block’s parameters to the arguments 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 `Proc#lambda?`.

Alias for: call