Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby parameter count rules

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}.

like image 629
Fire Lancer Avatar asked Mar 12 '23 19:03

Fire Lancer


1 Answers

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

like image 130
Thomas Avatar answered Apr 03 '23 16:04

Thomas