Proc
class Proc
父:对象
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 Show source
new → a_proc
创建Proc
绑定到当前上下文的新对象。Proc::new
可能仅在具有附加块的方法内没有块被调用,在这种情况下该块被转换为Proc
对象。
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;
}
公共实例方法
proc === obj → result_of_proc Show source
使用obj
#call这样的proc参数调用该块。它允许proc对象when
成为case语句中的子句的目标。
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
/* removed */
}
prcparams,... → obj Show source
调用该块,使用接近方法调用语义的东西将块的参数设置为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()
给定的参数。它是隐藏“呼叫”的语法糖。
对于使用创建的procs lambda或者->()如果将错误数量的参数传递给proc,则会生成错误。对于使用Proc.newor 创建的procs 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)
See also #lambda?.
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
/* removed */
}
arity → integer Show source
返回强制参数的数量。如果该块被声明为不带参数,则返回0.如果块已知需要正好n个参数,则返回n。如果该块具有可选参数,则返回-n-1,其中n是强制参数的数量,但不是lambda表达式且仅具有有限数量的可选参数的块除外; 在后一种情况下,返回n。关键字参数将被视为单个附加参数,如果任何关键字参数是强制参数,则该参数是必需参数。proc
没有参数声明的A 与声明||
为其参数的块相同。
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
static VALUE
proc_arity(VALUE self)
{
int arity = rb_proc_arity(self
return INT2FIX(arity
}
binding → binding Show source
返回与prc
关联的绑定。请注意,Kernel#eval
接受一个Proc
或一个Binding
对象作为其第二个参数。
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
bind->block.as.captured.self = binding_self;
bind->block.as.captured.code.iseq = env->iseq;
bind->block.as.captured.ep = env->ep;
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;
}
call(params,...) → obj Show source
调用该块,使用接近方法调用语义的东西将块的参数设置为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()
给定的参数。它是隐藏“呼叫”的语法糖。
对于使用创建的procs lambda或者->()如果将错误数量的参数传递给proc,则会生成错误。对于使用Proc.newor 创建的procs 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)
See also #lambda?.
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
/* removed */
}
curry → a_proc Show source
curry(arity) → a_proc
返回一个curried过程。如果给出可选的arity
参数,它将确定参数的数量。咖喱过程收到一些论据。如果提供了足够数量的参数,它将提供的参数传递给原始proc并返回结果。否则,返回另一个curried过程,其余的参数都会返回。
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 Show source
返回对应于proc主体的散列值。
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 Show source
true
参数处理非常僵化的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
and :: 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
总是定义一个没有技巧的方法,即使给出了非lambda 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
定义了一个没有技巧的方法。
VALUE
rb_proc_lambda_p(VALUE procval)
{
rb_proc_t *proc;
GetProcPtr(procval, proc
return proc->is_lambda ? Qtrue : Qfalse;
}
parameters → array Show source
返回此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()
返回包含此proc的Ruby源文件名和行号,或者nil
如果此proc未在Ruby中定义(即本机)。
VALUE
rb_proc_location(VALUE self)
{
return iseq_location(rb_proc_get_iseq(self, 0)
}
to_proc → proc Show source
将对象转换为Proc
对象的协议的一部分。类的实例Proc
只是返回自己。
static VALUE
proc_to_proc(VALUE self)
{
return self;
}
to_s → string Show source
返回此proc的唯一标识符,以及proc定义位置的指示。
static VALUE
proc_to_s(VALUE self)
{
const rb_proc_t *proc;
GetProcPtr(self, proc
return proc_to_s_(self, proc
}
别名: inspect
yield(params,...) → obj Show source
调用该块,使用接近方法调用语义的东西将块的参数设置为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()
给定的参数。它是隐藏“呼叫”的语法糖。
对于使用创建的procs lambda或者->()如果将错误数量的参数传递给proc,则会生成错误。对于使用Proc.newor 创建的procs 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)
See also #lambda?.
static VALUE
proc_call(int argc, VALUE *argv, VALUE procval)
{
/* removed */
}