Reputation: 18097
I want to know if something like this is possible, as hash.each does two different things based on arguments passed to block
{ "a"=>3, "b"=>2}.each {|k| puts k}
{ "a"=>3, "b"=>2}.each {|k,v| puts k}
Both output different things, and not just what's below..
a
b
..
a
b
I get this
a
3
b
2
..
a
b
So I want to know if there is a way to get my function to do something custom depending on the number of arguments of block being passed to it.
like this
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"
Upvotes: 0
Views: 88
Reputation: 36101
def my_method(&block)
if block.arity == 2
yield("hi", "bro")
else
yield("what's up")
end
end
Also look at the documentation since Proc#arity
has special behavior for default/named arguments, etc.
Upvotes: 3
Reputation: 369458
You can capture the block as a Proc
and then inspect its parameters:
def my_method(&blk)
blk.parameters
end
my_method {|a|}
# => [[:opt, :a]]
my_method {|a, b|}
# => [[:opt, :a], [:opt, :b]]
Note, however, that this is not what happens with Hash#each
. Hash#each
just follows the Enumerable#each
protocol and always yields one single item to the block, which is a two-element Array
of key and value. Normal block parameter binding then takes care of the rest:
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
Upvotes: 2