2

Just trying to understand how to collect arguments in Ruby, I came up with the following snippet, that seems to fail to collect keyword arguments in **kargs in some case:

def foo(i, j= 9, *args, k: 11, **kargs)
  puts "args: #{args}; kargs: #{kargs}"
end

foo(a: 7, b: 8)
# output: args: []; kargs: {}
foo(9, a: 7, b: 8)
# output: args: []; kargs: {:a=>7, :b=>8}
foo(9, 10, 13, a: 7, b: 8)
# output: args: [13]; kargs: {:a=>7, :b=>8}

I would like to know why it does not collect kargs in the first call to foo, while in the second call it does.

rellampec
  • 698
  • 6
  • 22

1 Answers1

5

It's because the first parameter i, is a required parameter (no default value), so, the first value passed to the method (in your first example, this is the hash {a: 7, b: 8}) is stored into it.

Then, since everything else is optional, the remaining values (if any, in this example, there are none) are filled in, as applicable. IE, the second parameter will go to j, unless it is a named parameter, then it goes to kargs (or k). The third parameter, and any remaining--up until the first keyword argument, go into args, and then any keyword args go to kargs

def foo(i, j= 9, *args, k: 11, **kargs)
  puts "i: #{i}; args: #{args}; kargs: #{kargs}"
end

foo(a: 7, b: 8)
# i: {:a=>7, :b=>8}; args: []; kargs: {}
rellampec
  • 698
  • 6
  • 22
Simple Lime
  • 10,790
  • 2
  • 17
  • 32
  • Thank you, I will have a look. I though that would only happen if I called by `foo({a: 7, b: 8})`. Perhaps that is a Ruby way to avoid an error when you call? – rellampec Aug 06 '18 at 01:08
  • is there a way to avoid that to happen? I am trying to build a `curry` function that includes both: `*args` and `**kw_args`. Please, see [this answer](https://stackoverflow.com/a/51699428/4352306) – rellampec Aug 06 '18 at 01:21
  • I have not tested it yet, but from what I read in `Ruby 3` it should fail to run `foo(a: 7, b: 8)`. Is that right? – rellampec Jan 11 '22 at 20:11