ruby – 为什么在“splatting”关键字参数时**是可选的?

鉴于此方法定义:

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

当我使用单个哈希参数调用方法时,无论**如何,哈希始终隐式转换为关键字参数:

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

我可以传递另一个(空)哈希作为变通方法:

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

但是,这看起来非常麻烦和笨拙.

我希望Ruby能够更好地处理这个数组,即:

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

并使用文字:

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

当前的实现看起来像一个缺陷,我期待它工作的方式似乎是显而易见的.

这是一个被忽视的边缘案例吗?我不这么认为.可能有一个很好的理由是它没有以这种方式实现.

有人可以开导我吗?

最佳答案 >至于缺乏**部分:

我的猜测是,为了使方法调用变得简单,Ruby总是一次解释key:value form而不用括号作为带有省略括号的哈希,无论它实际上是否会被解释为这样的哈希或关键字参数.

然后,为了将其解释为关键字参数,**隐式应用于它.

因此,如果您已经传递了显式哈希,它将不会对上面的过程产生影响,并且有空间将其解释为实际哈希或关键字参数.

当你明确地传递**时会发生什么:

method(**{key: value})

哈希是分解的:

method(key: value)

然后被解释为带有省略大括号的哈希:

method({key: value})

然后被解释为哈希或关键字参数.
>对于优先于其他参数的关键字参数,请参阅Ruby core:https://bugs.ruby-lang.org/issues/11967上的这篇文章.

点赞