检查传递的块参数有多少,然后使用不同的参数

时间:2015-08-04 14:47:38

标签: ruby

我想知道这样的事情是否可行,因为hash.each基于传递给块的参数做了两件不同的事情

{ "a"=>3, "b"=>2}.each {|k| puts k}

{ "a"=>3, "b"=>2}.each {|k,v| puts k}

两者都输出不同的东西,而不仅仅是下面的内容......

a
b
..
a
b

我明白了

a
3
b
2
..
a
b

所以我想知道是否有办法让我的函数根据传递给它的块的参数数量来自定义。

像这样

def my_method
   if yield.args==2
     yield("hi","bro")
   else 
     yield("what's up")
   end
end

my_method {|a,b| puts a; puts b;} #"hi" "bro"

my_method {|a| puts a; } #"whats up"

2 个答案:

答案 0 :(得分:3)

def my_method(&block)
  if block.arity == 2
    yield("hi", "bro")
  else 
    yield("what's up")
  end
end

另请查看documentation,因为Proc#arity对默认/命名参数有特殊行为等。

答案 1 :(得分:2)

您可以将块捕获为Proc,然后检查其参数:

def my_method(&blk)
  blk.parameters
end

my_method {|a|}
# => [[:opt, :a]]

my_method {|a, b|}
# => [[:opt, :a], [:opt, :b]]

但请注意, Hash#each会发生什么。 Hash#each仅遵循Enumerable#each协议,始终一个项发送到块,这是一个双元素Array关键和价值。然后,正常的块参数绑定负责其余部分:

def my_method
  yield ['Hello', 'World']
end

my_method {|a| p a }
# ["Hello", "World"]

my_method {|a, b| p a, b }
# "Hello"
# "World"

my_method {|a, b, c| p a, b, c }
# "Hello"
# "World"
# nil