4

鉴于此方法定义:

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}

当前的实现看起来像是一个缺陷,而我期望它的工作方式似乎很明显。

这是一个被忽视的边缘案例吗?我不这么认为。没有以这种方式实施可能是有充分理由的。

有人可以启发我吗?

4

1 回答 1

2
  1. 至于缺少的**部分:

    我的猜测是,为了使方法调用简单,Ruby 总是将key: value不带大括号的表单解释为带有省略大括号的散列,无论它实际上将被解释为这样的散列还是关键字参数。

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

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

    当您**明确通过时会发生什么:

    method(**{key: value})
    

    是散列被分解:

    method(key: value)
    

    then 被解释为带有省略括号的散列:

    method({key: value})
    

    then 被解释为散列或关键字参数。

  2. 至于优先于其他参数的关键字参数,请参阅 Ruby 核心上的这篇文章:https ://bugs.ruby-lang.org/issues/11967 。

于 2016-01-14T16:25:58.700 回答