Why is ** optional when “splatting” keyword arguments?

杀马特。学长 韩版系。学妹 提交于 2019-12-12 11:47:32

问题


Given this method definition:

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

When I invoke the 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, this looks pretty cumbersome and awkward.

I would have expected Ruby to handle this more like 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 was expecting it to work seems obvious.

Is this an overlooked edge case? I don't think so. There's probably a good reason that it wasn't implemented this way.

Can someone enlighten me, please?


回答1:


  1. As for the lack of ** part:

    My guess is that, to make method invocation simple, Ruby always once interprets the key: value form without the braces as a hash with omitted braces, whether it is actually going to be interpreted as such hash or as keyword arguments.

    Then, in order to interpret that as keyword arguments, ** is implicitly applied to it.

    Therefore, if you had passed an explicit hash, it will not make difference to the process above, and there is room for it to be interpreted either as an actual hash or as keyword arguments.

    What happens when you do pass ** explicitly like:

    method(**{key: value})
    

    is that the hash is decomposed:

    method(key: value)
    

    then is interpreted as a hash with omitted braces:

    method({key: value})
    

    then is interpreted either as a hash or as a keyword argument.

  2. As for keyword arguments having priority over other arguments, see this post on Ruby core: https://bugs.ruby-lang.org/issues/11967.



来源:https://stackoverflow.com/questions/34794043/why-is-optional-when-splatting-keyword-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!