我正在尝试设置一个以块作为参数的方法。我知道您是通过给最后一个参数一个&前缀来做到这一点的,但是一旦传递了它,我应该如何验证它呢?
例如,如果我想验证一个参数是字符串,我可以使用is_a?(String)。但是,如何验证是否收到了接受一个参数的块?或者是2?
发布于 2013-11-07 15:55:02
可以使用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与声明它的参数的块相同。
发布于 2013-11-07 16:24:23
块不是对象,所以您不能对它们做任何有用的事情(当然,除了对它们的yield )。
我的意思是,没有办法去称呼他们,他们甚至连一个名字都没有:
def foo
yield 'foo'
end
foo do |bar| puts bar end
# foo在foo中,块不绑定到任何变量,甚至不能引用它,因此显然也不能查询它的参数。
但是,您可以要求Ruby将块转换为Proc并将其绑定到参数。然后,您可以按名称引用它,您可以使用完整的Proc API,包括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]]但是,请注意,在Ruby中,“块的独立性”是一个毛茸茸的概念,因为块的参数绑定语义比较松散。块的参数绑定语义不同于方法的参数绑定语义,特别是当涉及到一致性时:
Array传递(就像参数被声明为*splat参数一样)。Array,其单个元素被作为参数传递(就像它们作为*splat参数被传递一样)。nil。总之,语义更接近赋值,而不是方法调用。
例如,您将注意到,尽管m1和m2在块中被声明为强制位置参数,但Proc#parameters将它们的类型列出为:opt,即可选参数。
换句话说,即使一个只声明一个参数的块仍然使用两个参数,而一个声明两个参数的块也可以用一个参数来调用。
这很有用的一个例子是:整个Enumerable混联是基于yield一个元素的方法的。但是,对于Hash,您确实需要处理两个参数,key, value。而且您可以这样做,因为Hash#each yield是一个由两个元素组成的Array,而一个声明两个参数但只接收一个参数的块将对其参数“拆分”该参数,这样您就可以得到绑定到key的键和绑定到value的值,而不必复制和粘贴所有Enumerable方法的双参数版本。
https://stackoverflow.com/questions/19840420
复制相似问题