Class: Proc

Inherits:
Object show all
Defined in:
proc.c

Overview

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

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Proc) new {|...| ... } + (Proc) new

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"

Overloads:

  • + (Proc) new {|...| ... }

    Yields:

    • (...)


# File 'proc.c'

/*
 *  call-seq:
 *     Proc.new {|...| block } -> a_proc
 *     Proc.new                -> a_proc
 *
 *  Creates a new <code>Proc</code> object, bound to the current
 *  context. <code>Proc::new</code> may be called without a block only
 *  within a method with an attached block, in which case that block is
 *  converted to the <code>Proc</code> 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;
}

Instance Method Details

- (Boolean) ==(other_proc)

Return true if prc is the same object as other_proc, or if they are both procs with the same body.



# File 'proc.c'

/*
 * call-seq:
 *   prc == other_proc   ->  true or false
 *
 * Return <code>true</code> if <i>prc</i> is the same object as
 * <i>other_proc</i>, 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;
}

- (Object) ===(obj)

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.



# File 'proc.c'

/*
 *  call-seq:
 *     prc === obj   -> result_of_proc
 *
 *  Invokes the block, with <i>obj</i> 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);
}

- (Object) ===(obj)

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.



# File 'proc.c'

/*
 *  call-seq:
 *     prc === obj   -> result_of_proc
 *
 *  Invokes the block, with <i>obj</i> 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);
}

- (Fixnum) arity

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


# File 'proc.c'

/*
 *  call-seq:
 *     prc.arity -> fixnum
 *
 *  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 <code>proc</code> with no argument declarations
 *  is the same a block declaring <code>||</code> 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);
}

- (Binding) binding

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


# File 'proc.c'

/*
 *  call-seq:
 *     prc.binding    -> binding
 *
 *  Returns the binding associated with <i>prc</i>. Note that
 *  <code>Kernel#eval</code> accepts either a <code>Proc</code> or a
 *  <code>Binding</code> 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;
}

- (Object) ===(obj)

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.



# File 'proc.c'

/*
 *  call-seq:
 *     prc === obj   -> result_of_proc
 *
 *  Invokes the block, with <i>obj</i> 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);
}

- (Object) clone

:nodoc:



# File 'proc.c'

/* :nodoc: */
static VALUE
proc_clone(VALUE self)
{
    VALUE procval = proc_dup(self);
    CLONESETUP(procval, self);
    return procval;
}

- (Proc) curry - (Proc) curry(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.

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


# File 'proc.c'

/*
  *  call-seq:
  *     prc.curry         -> a_proc
  *     prc.curry(arity)  -> a_proc
  *
  *  Returns a curried proc. If the optional <i>arity</i> 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);
}

- (Object) dup

:nodoc:



# File 'proc.c'

/* :nodoc: */
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->blockprocval = src->blockprocval;
    dst->envval = src->envval;
    dst->safe_level = src->safe_level;
    dst->is_lambda = src->is_lambda;

    return procval;
}

- (Boolean) ==(other_proc)

Return true if prc is the same object as other_proc, or if they are both procs with the same body.



# File 'proc.c'

/*
 * call-seq:
 *   prc == other_proc   ->  true or false
 *
 * Return <code>true</code> if <i>prc</i> is the same object as
 * <i>other_proc</i>, 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;
}

- (Integer) hash

Return hash value corresponding to proc body.



# File 'proc.c'

/*
 * call-seq:
 *   prc.hash   ->  integer
 *
 * Return 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);
}

- (Boolean) lambda?

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

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

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

Proc.new is same as proc.

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

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



# File 'proc.c'

/*
 * call-seq:
 *   prc.lambda? -> true or false
 *
 * 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
 *
 * Proc#lambda? is a predicate for the tricks.
 * It returns true if no tricks.
 *
 *   lambda {}.lambda?            #=> true
 *   proc {}.lambda?              #=> false
 *
 * Proc.new is same as proc.
 *
 *   Proc.new {}.lambda?          #=> false
 *
 * lambda, proc and Proc.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.
 *
 */

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

    return proc->is_lambda ? Qtrue : Qfalse;
}

- (Array) parameters

returns the parameter information of this proc.

prc = lambda{|x, y=42, *rest|}
prc.parameters  #=> [[:req, :x], [:opt, :y], [:rest, :rest]]


# File 'proc.c'

/*
 * call-seq:
 *    proc.parameters  -> array
 *
 * returns the parameter information of this proc.
 *
 *    prc = lambda{|x, y=42, *rest|}
 *    prc.parameters  #=> [[:req, :x], [:opt, :y], [:rest, :rest]]
 */

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

- (Array) source_location

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



# File 'proc.c'

/*
 * call-seq:
 *    prc.source_location  -> [String, Fixnum]
 *
 * 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));
}

- (Proc) to_proc

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



# File 'proc.c'

/*
 *  call-seq:
 *     prc.to_proc -> prc
 *
 *  Part of the protocol for converting objects to <code>Proc</code>
 *  objects. Instances of class <code>Proc</code> simply return
 *  themselves.
 */

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

- (String) to_s

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



# File 'proc.c'

/*
 * call-seq:
 *   prc.to_s   -> string
 *
 * 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;
}

- (Object) ===(obj)

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.



# File 'proc.c'

/*
 *  call-seq:
 *     prc === obj   -> result_of_proc
 *
 *  Invokes the block, with <i>obj</i> 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);
}