Spec-Zone.ru › Ruby 2.3

класс Proc

Родитель:
Object

Proc объекты — это блоки кода, которые связаны с набором локальных переменных. После связывания код может вызываться в разных контекстах и по-прежнему обращаться к этим переменным.

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

Публичные методы класса

new {|...| block } → a_proc Показать исходный код
new → a_proc
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;
}

Создаёт новый Proc объект, связанный с текущим контекстом. Proc::new может вызываться без блока только внутри метода с прикреплённым блоком, в этом случае этот блок преобразуется в объект Proc.

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

Методы экземпляра публичного интерфейса

proc === obj → результат_вызова_proc Показать исходный код
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
    VALUE vret;
    const rb_block_t *blockptr = 0;
    const rb_iseq_t *iseq;
    rb_proc_t *proc;
    VALUE passed_procval;
    GetProcPtr(procval, proc);

    iseq = proc->block.iseq;
    if (RUBY_VM_IFUNC_P(iseq) || iseq->body->param.flags.has_block) {
        if (rb_block_given_p()) {
            rb_proc_t *passed_proc;
            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);
    RB_GC_GUARD(passed_procval);
    return vret;
}

Вызывает блок с obj в качестве параметра proc, как в #call. Это позволяет использовать объект proc в качестве целевого объекта для when в операторе case.

prc[params,...] → obj Показать исходный код
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
    VALUE vret;
    const rb_block_t *blockptr = 0;
    const rb_iseq_t *iseq;
    rb_proc_t *proc;
    VALUE passed_procval;
    GetProcPtr(procval, proc);

    iseq = proc->block.iseq;
    if (RUBY_VM_IFUNC_P(iseq) || iseq->body->param.flags.has_block) {
        if (rb_block_given_p()) {
            rb_proc_t *passed_proc;
            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);
    RB_GC_GUARD(passed_procval);
    return vret;
}

Вызывает блок, устанавливая параметры блока на значения в params, используя что-то близкое к семантике вызова метода. Возвращает значение последнего выражения, вычисленного в блоке.

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]

Обратите внимание, что prc.() вызывает prc.call() с заданными параметрами. Это синтаксический сахар для скрытия «call».

Для proc, созданных с использованием lambda или ->(), генерируется ошибка, если передано неверное количество параметров для proc. Для proc, созданных с использованием Proc.new или Kernel.proc, дополнительные параметры игнорируются, а отсутствующие параметры устанавливаются в 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)

См. также #lambda?.

arity → fixnum Показать исходный код
static VALUE
proc_arity(VALUE self)
{
    int arity = rb_proc_arity(self);
    return INT2FIX(arity);
}

Возвращает количество обязательных аргументов. Если блок объявлен без аргументов, возвращает 0. Если блок известен, что принимает ровно n аргументов, возвращает n. Если блок имеет необязательные аргументы, возвращает -n-1, где n — количество обязательных аргументов, за исключением блоков, которые не являются лямбдами и имеют только конечное количество необязательных аргументов; в последнем случае возвращает n. Аргументы ключевых слов будут рассматриваться как один дополнительный аргумент, который является обязательным, если какой-либо аргумент ключевого слова является обязательным. A proc без объявления аргументов эквивалентен блоку, объявляющему || в качестве аргументов.

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   { |x=0| }.arity         #=>  0
lambda { |x=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
proc   { |a, x:0, y:0| }.arity #=>  1
lambda { |a, x:0, y:0| }.arity #=> -2
binding → binding Показать исходный код
static VALUE
proc_binding(VALUE self)
{
    VALUE bindval, envval;
    const rb_proc_t *proc;
    const rb_iseq_t *iseq;
    rb_binding_t *bind;

    GetProcPtr(self, proc);
    envval = rb_vm_proc_envval(proc);
    iseq = proc->block.iseq;
    if (SYMBOL_P(iseq)) goto error;
    if (RUBY_VM_IFUNC_P(iseq)) {
        struct vm_ifunc *ifunc = (struct vm_ifunc *)iseq;
        if (IS_METHOD_PROC_IFUNC(ifunc)) {
            VALUE method = (VALUE)ifunc->data;
            envval = env_clone(envval, method_receiver(method), method_cref(method));
            iseq = rb_method_iseq(method);
        }
        else {
          error:
            rb_raise(rb_eArgError, "Can't create Binding from C level Proc");
        }
    }

    bindval = rb_binding_alloc(rb_cBinding);
    GetBindingPtr(bindval, bind);
    bind->env = envval;

    if (iseq) {
        rb_iseq_check(iseq);
        bind->path = iseq->body->location.path;
        bind->first_lineno = FIX2INT(rb_iseq_first_lineno(iseq));
    }
    else {
        bind->path = Qnil;
        bind->first_lineno = 0;
    }

    return bindval;
}

Возвращает привязку, связанную с prc. Обратите внимание, что Kernel#eval принимает в качестве второго параметра либо Proc, либо объект Binding.

def fred(param)
  proc {}
end

b = fred(99)
eval("param", b.binding)   #=> 99
call(params,...) → obj Показать исходный код
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
    VALUE vret;
    const rb_block_t *blockptr = 0;
    const rb_iseq_t *iseq;
    rb_proc_t *proc;
    VALUE passed_procval;
    GetProcPtr(procval, proc);

    iseq = proc->block.iseq;
    if (RUBY_VM_IFUNC_P(iseq) || iseq->body->param.flags.has_block) {
        if (rb_block_given_p()) {
            rb_proc_t *passed_proc;
            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);
    RB_GC_GUARD(passed_procval);
    return vret;
}

Вызывает блок, устанавливая параметры блока на значения в params, используя что-то близкое к семантике вызова метода. Возвращает значение последнего выражения, вычисленного в блоке.

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]

Обратите внимание, что prc.() вызывает prc.call() с заданными параметрами. Это синтаксический сахар для скрытия «call».

Для proc, созданных с использованием lambda или ->(), генерируется ошибка, если передано неверное количество параметров для proc. Для proc, созданных с использованием Proc.new или Kernel.proc, дополнительные параметры игнорируются, а отсутствующие параметры устанавливаются в 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)

См. также #lambda?.

curry → a_proc Показать исходный код
curry(arity) → a_proc
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);
}

Возвращает замыкание proc. Если необязательный аргумент arity задан, он определяет количество аргументов. Замыкание proc принимает некоторые аргументы. Если предоставлено достаточное количество аргументов, оно передает эти аргументы исходному proc и возвращает результат. В противном случае возвращает другое замыкание proc, которое принимает оставшиеся аргументы.

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
hash → integer Показать исходный код
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);
}

Возвращает значение хэша, соответствующее телу proc.

См. также Object#hash.

inspect()
Псевдоним для: to_s
lambda? → true или false Показать исходный код
VALUE
rb_proc_lambda_p(VALUE procval)
{
    rb_proc_t *proc;
    GetProcPtr(procval, proc);

    return proc->is_lambda ? Qtrue : Qfalse;
}

Возвращает true для объекта Proc, для которого обработка аргументов жёсткая. Такие proc обычно генерируются lambda.

Объект Proc, сгенерированный proc игнорирует дополнительные аргументы.

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

Он предоставляет nil для отсутствующих аргументов.

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

Он расширяет единственный аргумент массива.

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

Объект Proc, сгенерированный аргументом lambda не имеет таких уловок.

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? — это предикат для этих уловок. Возвращает true если никакие уловки не применимы.

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

::new такое же, как proc.

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

lambda, proc и ::new сохраняют уловки объекта Proc, заданного аргументом &.

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

Объект Proc, сгенерированный аргументом & имеет эти уловки.

def n(&b) b.lambda? end
n {}                         #=> false

Аргумент & сохраняет уловки, если объект Proc задан аргументом &.

n(&lambda {})                #=> true
n(&proc {})                  #=> false
n(&Proc.new {})              #=> false

Объект Proc, преобразованный из метода, не имеет уловок.

def m() end
method(:m).to_proc.lambda?   #=> true

n(&method(:m))               #=> true
n(&method(:m).to_proc)       #=> true

define_method обрабатывается так же, как определение метода. Определённый метод не имеет уловок.

class C
  define_method(:d) {}
end
C.new.d(1,2)       #=> ArgumentError
C.new.method(:d).to_proc.lambda?   #=> true

define_method всегда определяет метод без уловок, даже если задан объект не-лямбда Proc. Это единственное исключение, где уловки не сохраняются.

class C
  define_method(:e, &proc {})
end
C.new.e(1,2)       #=> ArgumentError
C.new.method(:e).to_proc.lambda?   #=> true

Это исключение гарантирует, что методы никогда не имеют уловок, и упрощает создание обёрток для определения методов, которые ведут себя как обычно.

class C
  def self.def2(name, &body)
    define_method(name, &body)
  end

  def2(:f) {}
end
C.new.f(1,2)       #=> ArgumentError

Обёртка def2 определяет метод, который не имеет уловок.

parameters → array Показать исходный код
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);
}

Возвращает информацию о параметрах этого proc.

prc = lambda{|x, y=42, *other|}
prc.parameters  #=> [[:req, :x], [:opt, :y], [:rest, :other]]
source_location → [Строка, Число] Показать исходный код
VALUE
rb_proc_location(VALUE self)
{
    return iseq_location(rb_proc_get_iseq(self, 0));
}

Возвращает имя файла и номер строки Ruby, содержащие этот proc, или nil, если этот proc не был определён в Ruby (т.е. нативный).

to_proc → proc Показать исходный код
static VALUE
proc_to_proc(VALUE self)
{
    return self;
}

Часть протокола для преобразования объектов в объекты Proc. Экземпляры класса Proc просто возвращают себя.

to_s → строка Показать исходный код
static VALUE
proc_to_s(VALUE self)
{
    VALUE str = 0;
    rb_proc_t *proc;
    const char *cname = rb_obj_classname(self);
    const 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) && rb_iseq_check(iseq)) {
        int first_lineno = 0;

        if (iseq->body->line_info_table) {
            first_lineno = FIX2INT(rb_iseq_first_lineno(iseq));
        }
        str = rb_sprintf("#<%s:%p@%"PRIsVALUE":%d%s>", cname, (void *)self,
                         iseq->body->location.path, first_lineno, is_lambda);
    }
    else if (SYMBOL_P(iseq)) {
        str = rb_sprintf("#<%s:%p(&%+"PRIsVALUE")%s>", cname, (void *)self,
                         (VALUE)iseq, 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;
}

Возвращает уникальный идентификатор этого proc вместе с указанием места определения proc.

Также алиасируется как: inspect
yield(params,...) → obj Показать исходный код
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
    VALUE vret;
    const rb_block_t *blockptr = 0;
    const rb_iseq_t *iseq;
    rb_proc_t *proc;
    VALUE passed_procval;
    GetProcPtr(procval, proc);

    iseq = proc->block.iseq;
    if (RUBY_VM_IFUNC_P(iseq) || iseq->body->param.flags.has_block) {
        if (rb_block_given_p()) {
            rb_proc_t *passed_proc;
            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);
    RB_GC_GUARD(passed_procval);
    return vret;
}

Вызывает блок, устанавливая параметры блока на значения в params, используя что-то близкое к семантике вызова метода. Возвращает значение последнего выражения, вычисленного в блоке.

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]

Обратите внимание, что prc.() вызывает prc.call() с заданными параметрами. Это синтаксический сахар для скрытия «call».

Для proc, созданных с использованием lambda или ->(), генерируется ошибка, если передано неверное количество параметров для proc. Для proc, созданных с использованием Proc.new или Kernel.proc, дополнительные параметры игнорируются, а отсутствующие параметры устанавливаются в 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)

См. также #lambda?.

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API