【发布时间】:2015-03-05 11:07:40
【问题描述】:
在方法调用中对空数组进行 Splat 扩展可以有效地将参数减少为空(为清楚起见添加了空括号):
def foo()
end
def bar(*args)
foo(*args)
end
bar(1) # ArgumentError, as expected
bar() # works
但这同样不适用于哈希参数:
def baz()
end
def qux(**opts)
baz(**opts)
end
qux # ArgumentError, **opts becomes {}
我可以通过显式检查空哈希来解决这个问题:
def quux(callable, **opts)
if opts.empty?
callable.()
else
callable.(**opts)
end
end
c = ->{}
quux(c) # works
但是有没有更好/更好的方法来做到这一点,或者是否计划改变这种行为?在编写bar 和qux 时,我不知道foo 和baz 的签名,因为后者是类似工厂的构造函数包装器的一部分。
【问题讨论】:
-
为什么需要使用
**opts?*args也应该与关键字参数一起使用。 -
我想得越久,我就越觉得这实际上可能是 Ruby 中的一个错误。如果
foo(*[])有效,baz(**{})也应该有效。 -
@PatrickOscity 使用 args 很好。不知何故忘记了这一点。我今天学习了 double splat 语法,并且在使用它方面可能变得有点专心。只需使用
*args即可适用于我刚刚尝试过的每种情况,包括可选、可选关键字和必需关键字参数的混合。所以我现在实际上不需要这个工作。但我仍然同意你的第二条评论,我认为这是不直观的,可能是无意的。我会在错误跟踪器上四处寻找并提交报告。 -
我认为你的直觉在这里是错误的。您希望
opts哈希应该扩展到什么?数组 splat 运算符*可以 1:1 将Array元素转换为 普通参数列表,这对于Hash来说是不可能且明确的。散列的“扩展”需要一个容器对象。试试{key: 123, **opts}和[:key, 123, **opts]看看我的意思。 -
@DavidUnric 我明白你的意思,但是通过引入关键字参数,我认为我的直觉至少和你的一样合理:
*[]扩展到零位置参数,所以**{}应该扩展到零命名参数。可以说这取决于您的观点,但在方法调用的上下文中,有理由让它按照我预期的方式工作。