我正在尝试建立一个方法,它以一个块作为参数。我知道你通过给最后一个参数一个&前缀来做到这一点,但是一旦它被传递了,我应该如何验证它呢?如果我想验证一个参数是字符串,我可以使用is_a?(String)。但是我如何验证我已经收到了一个接受一个参数的块?还是两个?
is_a?(String)
jpfvwuh41#
你可以使用Proc#arity方法来检查块接受了多少个参数:
Proc#arity
def foo(&block) puts block.arity end foo { } # => 0 foo { |a| } # => 1 foo { |a, b| } # => 2
字符串在文档中:返回不会被忽略的参数数。如果块声明为不带参数,则返回0。如果已知块正好有n个参数,则返回n。如果块具有可选参数,则返回-n-1,其中n是强制参数的数量。没有参数声明的proc与声明||作为其论据。
xnifntxz2#
块不是对象,所以不能对它们做任何有用的事情(当然,除了对它们使用yield)。我的意思是,没有办法提到他们,他们甚至没有绑定到一个名字:
yield
def foo yield 'foo' end foo do |bar| puts bar end # foo
字符串在foo中,块没有绑定到任何变量,甚至不能引用它,所以显然也不能查询它的参数。但是,您可以要求Ruby将块转换为Proc并将其绑定到参数。然后,您可以通过名称引用它,* 和 * 您可以使用完整的Proc API,包括Proc#parameters:
foo
Proc
Proc#parameters
def foo(&blk) blk.parameters end foo do |m1, m2, o1=:o1, o2=:o2, *splat, m3, m4, ok1: :ok1, mk1:, mk2:, ok2: :ok2, **ksplat, &blk| end # => [[:opt, :m1], # [:opt, :m2], # [:opt, :o1], # [:opt, :o2], # [:rest, :splat], # [:opt, :m3], # [:opt, :m4], # [:keyreq, :mk1], # [:keyreq, :mk2], # [:key, :ok1], # [:key, :ok2], # [:keyrest, :ksplat], # [:block, :blk]]
型然而,请注意,“块的arity”的概念在Ruby中是一个模糊的概念,因为块的参数绑定语义是松散的。块的参数绑定语义与方法的参数绑定语义不同,特别是在arity方面:
Array
*splat
nil
总而言之,与方法调用相比,其语义更接近于赋值。例如,您会注意到,即使m1和m2在块中被声明为强制位置参数,Proc#parameters也将其类型列为:opt,即可选参数。换句话说:即使一个块只声明一个参数,仍然需要两个参数,而一个块声明两个参数,可以调用只有一个参数。这是一个有用的例子:整个Enumerable mixin是基于yield一个 * 单一 * 元素的方法。但是,对于Hash,您实际上需要处理两个参数key, value。你可以,因为Hash#eachyield是一个Array,有两个元素,一个声明了两个参数但只接收一个参数的块会在它的参数之间“splat”这个参数,这样你就可以得到绑定到key的键和绑定到value的值,而不必复制和粘贴两个-所有Enumerable方法的参数版本。
m1
m2
:opt
Enumerable
Hash
key, value
Hash#each
key
value
2条答案
按热度按时间jpfvwuh41#
你可以使用
Proc#arity
方法来检查块接受了多少个参数:字符串
在文档中:
返回不会被忽略的参数数。如果块声明为不带参数,则返回0。如果已知块正好有n个参数,则返回n。如果块具有可选参数,则返回-n-1,其中n是强制参数的数量。没有参数声明的proc与声明||作为其论据。
xnifntxz2#
块不是对象,所以不能对它们做任何有用的事情(当然,除了对它们使用
yield
)。我的意思是,没有办法提到他们,他们甚至没有绑定到一个名字:
字符串
在
foo
中,块没有绑定到任何变量,甚至不能引用它,所以显然也不能查询它的参数。但是,您可以要求Ruby将块转换为
Proc
并将其绑定到参数。然后,您可以通过名称引用它,* 和 * 您可以使用完整的Proc
API,包括Proc#parameters
:型
然而,请注意,“块的arity”的概念在Ruby中是一个模糊的概念,因为块的参数绑定语义是松散的。块的参数绑定语义与方法的参数绑定语义不同,特别是在arity方面:
Array
传递(就像参数已被声明为*splat
参数一样)。Array
,其单个元素将作为参数传递(就像它们已作为*splat
参数传递)。nil
。总而言之,与方法调用相比,其语义更接近于赋值。
例如,您会注意到,即使
m1
和m2
在块中被声明为强制位置参数,Proc#parameters
也将其类型列为:opt
,即可选参数。换句话说:即使一个块只声明一个参数,仍然需要两个参数,而一个块声明两个参数,可以调用只有一个参数。
这是一个有用的例子:整个
Enumerable
mixin是基于yield
一个 * 单一 * 元素的方法。但是,对于Hash
,您实际上需要处理两个参数key, value
。你可以,因为Hash#each
yield
是一个Array
,有两个元素,一个声明了两个参数但只接收一个参数的块会在它的参数之间“splat”这个参数,这样你就可以得到绑定到key
的键和绑定到value
的值,而不必复制和粘贴两个-所有Enumerable
方法的参数版本。