What are the rules in Ruby regarding the number of parameters for the various function-like constructs and how they are called?
e.g. I noticed that when blocks with multiple parameters, get passed a single array parameter, it gets expanded, and this does not seem to apply to methods. I often see this with Enumerable module methods on a Hash object.
{a: 5}.map{|x| x} # [[:a, 5]]
{a: 5}.map{|k, v| [k, v]} # [[:a, 5]]
[[:a, 5]].map{|x| x} # [[:a, 5]]
[[:a, 5]].map{|k, v| [k, v]} # [[:a, 5]]
proc1 = Proc.new{|x| x}
proc1.call 5 # 5
proc1.call 5, 6 # 5
proc1.call [5, 6] # [5, 6]
proc2 = Proc.new{|k, v| [k, v]}
proc2.call 5 # [5, nil]
proc2.call 5, 6 # [5, 6]
proc2.call [5, 6] # [5, 6], not [[5, 6], nil]
def f(k, v); [k, v] end
f 5 # ArgumentError
f 5, 6 # [5, 6]
f [5, 6] # ArgumentError
def g(*vargs); vargs end
g 5 # [5]
g 5, 6 # [5, 6]
g [5, 6] # [[5, 6]]
However the documentation for Proc.call does not seem to mention this.
Then there is also lambda's that are slightly different, methods as Proc's using &:name
, and maybe some others. And I am not entirely sure Proc.new{|x| x}.call
is exactly the same as the yield
in a method_that_takes_a_block{|x| x}
.
The reason behind this is multiple variable assignment and auto-splat
Let's take your proc2 exemple (with an additional intersting use case) :
proc2 = Proc.new{|k, v| [k, v]}
proc2.call 5 # [5, nil]
proc2.call 5, 6 # [5, 6]
proc2.call [5, 6] # [5, 6], not [[5, 6], nil]
proc2.call [5, 6, 7] # [5, 6]
with ruby you can do a multiple variable assignement:
k, v= 5 # => k=5, v=nil
k, v= 5, 6 # => k=5, v=6
k, v= 5, 6, 7 # => k=5, v=6, 7 is not assigned
You can also expand an array with the splat operator:
k, v= *[5, 6] # => k=5, v=6
You can also pack multiple variable in an array with the splat operator:
k, *v= *[5, 6, 7] # => k=5, v=[6, 7]
ruby can auto splat when suitable:
k, v= [5, 6] # => k=5, v=6
k, v= [5, 6, 7] # => k=5, v=6, 7 is not assigned
as far as I know auto-splat only applies on variables and Proc
parameters assignment
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With