Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can this Ruby method call be made without **{} at the end?

I have a method defined like this:

def woot(a = nil, b: nil)
  ...
end

What is the least ugly way to pass a Hash instance to a when b is omitted?

I tried

woot(x: 1)
woot({x: 1})
h = {x: 1}
woot(h)

but they all raise

ArgumentError: unknown keyword: x

The only way to make the call that I have figured out is

woot({x: 1}, **{})

Is there a nicer way?

like image 363
jedediah Avatar asked Nov 10 '22 20:11

jedediah


1 Answers

Your first argument is optional, so Ruby assumes that the hash you're passing is for the named arguments (*).

I don't think there's a better workaround, though this is a bit shorter (but not necessarily cleaner):

woot({x: 1}, {})

If I were you I would change the method signature to resolve the ambiguity.


(*): Well, not always: woot({1=>3}) will happily pass the hash to the first optional argument.

Even weirder, in case of woot({1=> 5, :b => 4}), Ruby will split the dictionary, and pass {1=>5} to the first optional parameter.

Looks like it tries to grab the named parameters first (and will complain about not existing names), then pass the rest to the optional parameters.

But I would love to see some language-lawyer explanation...

like image 90
Karoly Horvath Avatar answered Dec 29 '22 05:12

Karoly Horvath