首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Ruby:如何检查一个块接受多少参数?

Ruby:如何检查一个块接受多少参数?
EN

Stack Overflow用户
提问于 2013-11-07 15:52:28
回答 2查看 1.7K关注 0票数 4

我正在尝试设置一个以块作为参数的方法。我知道您是通过给最后一个参数一个&前缀来做到这一点的,但是一旦传递了它,我应该如何验证它呢?

例如,如果我想验证一个参数是字符串,我可以使用is_a?(String)。但是,如何验证是否收到了接受一个参数的块?或者是2?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-07 15:55:02

可以使用Proc#arity方法检查块接受多少参数:

代码语言:javascript
运行
复制
def foo(&block)
  puts block.arity
end

foo { }        # => 0
foo { |a| }    # => 1
foo { |a, b| } # => 2

从文件中:

返回不会被忽略的参数数。如果声明该块不接受参数,则返回0。如果该块已知完全带有n个参数,则返回n。如果该块具有可选参数,则返回-n-1,其中n是强制参数的数目。没有参数声明的proc与声明它的参数的块相同。

票数 11
EN

Stack Overflow用户

发布于 2013-11-07 16:24:23

块不是对象,所以您不能对它们做任何有用的事情(当然,除了对它们的yield )。

我的意思是,没有办法去称呼他们,他们甚至连一个名字都没有:

代码语言:javascript
运行
复制
def foo
  yield 'foo'
end

foo do |bar| puts bar end
# foo

foo中,块不绑定到任何变量,甚至不能引用它,因此显然也不能查询它的参数。

但是,您可以要求Ruby将块转换为Proc并将其绑定到参数。然后,您可以按名称引用它,您可以使用完整的Proc API,包括Proc#parameters

代码语言:javascript
运行
复制
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

总之,语义更接近赋值,而不是方法调用。

例如,您将注意到,尽管m1m2在块中被声明为强制位置参数,但Proc#parameters将它们的类型列出为:opt,即可选参数。

换句话说,即使一个只声明一个参数的块仍然使用两个参数,而一个声明两个参数的块也可以用一个参数来调用。

这很有用的一个例子是:整个Enumerable混联是基于yield一个元素的方法的。但是,对于Hash,您确实需要处理两个参数,key, value。而且您可以这样做,因为Hash#each yield是一个由两个元素组成的Array,而一个声明两个参数但只接收一个参数的块将对其参数“拆分”该参数,这样您就可以得到绑定到key的键和绑定到value的值,而不必复制和粘贴所有Enumerable方法的双参数版本。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19840420

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档