【问题标题】:Can this Ruby method call be made without **{} at the end?可以在没有 **{} 的情况下调用这个 Ruby 方法吗?
【发布时间】:2015-03-16 10:38:31
【问题描述】:

我有一个这样定义的方法:

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

b 被省略时,将Hash 实例传递给a 的最不难看的方法是什么?

我试过了

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

但他们都加注

ArgumentError: unknown keyword: x

我想出的唯一拨打电话的方法是

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

有更好的方法吗?

【问题讨论】:

标签: ruby argument-passing


【解决方案1】:

如果您不希望 b 的默认值发生变化,永远,那么显式传递它怎么样?

woot({x: 1}, b: nil)

当然,如果b 的默认值确实在某一天发生了变化,您仍然会传入nil,从而覆盖该调用的b 值到其他东西比它的新默认值。

【讨论】:

    【解决方案2】:

    您的第一个参数是可选的,因此 Ruby 假定您传递的哈希是用于命名参数 (*)。

    我不认为有更好的解决方法,虽然这有点短(但不一定更干净):

    woot({x: 1}, {})
    

    如果我是你,我会更改方法签名以解决歧义。


    (*):嗯,并非总是如此:woot({1=>3}) 会很乐意将哈希传递给第一个可选参数。

    更奇怪的是,如果是woot({1=> 5, :b => 4}),Ruby 会拆分字典,并将{1=>5} 传递给第一个可选参数。

    看起来它首先尝试获取命名参数(并且会抱怨不存在的名称),然后将其余的传递给可选参数。

    但我希望看到一些语言律师的解释......

    【讨论】:

    • 哇,你说得对。那更奇怪了。不仅参数的类型改变了它的解析方式,而且参数中包含的键的类型。最不意外的原则就到此为止了。
    • 还有更多惊喜... :) 不幸的是,Ruby 主要是由 MRI 所做的“定义”,所以我很难引用段落,您可能需要查找 MRI 源...跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-30
    • 1970-01-01
    • 2018-04-29
    • 2020-05-29
    相关资源
    最近更新 更多