Ruby 检查正在传递的块有多少个参数,然后使用不同的参数调用yield

Ruby 检查正在传递的块有多少个参数,然后使用不同的参数调用yield,ruby,Ruby,我想知道这样的事情是否可行,比如hash.each根据传递给block的参数做两件不同的事情 { "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

我想知道这样的事情是否可行,比如hash.each根据传递给block的参数做两件不同的事情

{ "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"
另外请看一下,因为
Proc#arity
对于默认/命名参数等具有特殊行为


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

您可以将块捕获为
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
协议,始终为块生成一个单独的项,即键和值的两元素数组。然后,普通块参数绑定会处理其余的部分:

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

您可以将块捕获为
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
协议,始终为块生成一个单独的项,即键和值的两元素数组。然后,普通块参数绑定会处理其余的部分:

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

您现在应该真正使用
Proc#参数了
Proc#arity
随着可选参数、rest参数和关键字参数的引入,它变得越来越无用。我不同意。这正是OP所要求的。它很简洁,不需要进一步修改所传递的参数。
每个
是如何实现的?@MuhammadUmer,正如@Jorg解释的那样。您可以看到,如果您运行
{a:1,b:2}.each.to_a
,它将被转换为数组
[key,value]
。只是,如果需要两个参数,数组将被解包,如果不需要,数组对将在一个参数中给出。根据参数的不同,没有什么不同的情况发生。您现在应该真正使用
Proc#parameters
Proc#arity
随着可选参数、rest参数和关键字参数的引入,它变得越来越无用。我不同意。这正是OP所要求的。它很简洁,不需要进一步修改所传递的参数。
每个
是如何实现的?@MuhammadUmer,正如@Jorg解释的那样。您可以看到,如果您运行
{a:1,b:2}.each.to_a
,它将被转换为数组
[key,value]
。只是,如果需要两个参数,数组将被解包,如果不需要,数组对将在一个参数中给出。你能详细说明我在看什么吗对不起,我只是重新读了你的问题,看我误解了,所以我删除了以前的评论。你能详细说明我在看什么吗?对不起,我只是重新读了你的问题,看我误解了,所以我删除了以前的评论。