Why ** optional when the keyword arguments are "splatting"?

Given this method definition:

def foo(a = nil, b: nil)
  p a: a, b: b
end

When I call a method with a single hash argument, the hash is always implicitly converted to keyword arguments, regardless of **:

hash = {b: 1}
foo(hash)     #=> {:a=>nil, :b=>1}
foo(**hash)   #=> {:a=>nil, :b=>1}

I can pass another (empty) hash as a workaround:

foo(hash, {}) #=> {:a=>{:b=>1}, :b=>nil}

But , it looks rather bulky and uncomfortable.

I would expect Ruby to handle this more, how arrays are handled, i.e.:

foo(hash)     #=> {:a=>{:b=>1}, :b=>nil}
foo(**hash)   #=> {:a=>nil, :b=>1}

And using literals:

foo({b: 1})   #=> {:a=>{:b=>1}, :b=>nil}
foo(b: 1)     #=> {:a=>nil, :b=>1}
foo(**{b: 1}) #=> {:a=>nil, :b=>1}

The current implementation looks like a flaw, and the way I expected it to work seems obvious.

Is this a wonderful edge case? I do not think so. There is probably a good reason that it was not implemented in this way.

Can someone enlighten me please?

+4
1
+2

Source: https://habr.com/ru/post/1624307/


All Articles