Ruby double splat parameter is too greedy with Hash argument

Viewed 755

In Ruby 2.4.1, I have a method like this:

def example(*args, **kwargs)
  p args
  p kwargs
end

I can pass in positional arguments that are not Hash just fine:

irb(main):001:0> example("Greetings")
["Greetings"]
{}

And if I want to use named parameters, that's fine, too:

irb(main):002:0> example(something: 42)
[]
{:something=>42}

But trying to pass a Hash as a positional argument, this happens:

irb(main):002:0> example({something: 42})
[]
{:something=>42}

I want *args to take {something: 42}, not **kwargs.

The positional arguments have to be optional, but even if *args were arg=nil, the double-splat is still too greedy:

irb(main):001:0> def example(arg=nil, **kwargs)
irb(main):002:1>   p arg
irb(main):003:1>   p kwargs
irb(main):004:1> end
=> :example

irb(main):005:0> example({"key":"value"})
nil
{:key=>"value"}

irb(main):006:0> example({"key":"value"}, this_is: "in kwargs")
{:key=>"value"}
{:this_is=>"in kwargs"}

How can I pass a Hash as a positional argument when the method takes ** as well?

1 Answers
Related