根据这篇文章,可以在splat参数后具有可选的关键词参数。如果splat参数引入数组数组,则可以使用,而不是当它是哈希数组
的数组时例如,如果被调用的方法定义为
def call(*scores, alpha: nil)
puts scores
end
然后这起作用
scores = [[1,2],[3,4]]
call(*scores)
但这不是
scores = [ {a: 1}, {b: 3}]
call(*scores)
给出以下(使用Ruby 2.4.4)
ArgumentError: unknown keyword: b
但这有效
scores = [ {a: 1}, {b: 3}]
call(*scores, alpha: nil)
这里出了什么问题?
splat操作员将数组分配为参数。
但是,如果将其包裹在数组中,它又可以工作,但是现在它是数组中的一个数组,仍然被视为传递给您方法的单个参数。
call([*scores]) #no error
,但还说明为什么您会出现错误查看此处会发生什么:
def call(*scores, alpha: nil)
puts scores.inspect
end
call(*scores[0]) #=> #[[:a, 1]]
更新:感谢@stefan,错误的原因实际上是您的方法接受关键字参数,这显然是已知的错误。请参阅Ruby
中的关键字参数解开包装(SPL)您上一个示例起作用的原因是,通过将第二个参数传递给您的方法,Splat将第一个参数处理为数组,而不是试图将其分为2个参数。
更多,请参阅Ruby,Splat的源代码?
另请参见https://www.rubyguides.com/2018/07/ruby-operators/#ruby_splat_operator
*
将数组元素转换为参数列表,因此:
call(*[{a: 1}, {b: 3}])
等效于:
call({a: 1}, {b: 3})
Ruby还隐式地转换为关键字参数(无**
),因此上述等同于:†
call({a: 1}, b: 3)
因此, {a: 1}
被视为位置参数,而 b: 3
(或 {b: 3}
)作为关键字参数。而且由于 call
不使用名为 b
的关键字参数,您得到了 ArgumentError: unknown keyword: b
。
为了避免这种情况,您可以将额外的空哈希‡作为最后一个参数:
call({a:1}, {b:2}, {})
或:
call(*[{a:1}, {b:2}], {})
或
scores = [{a:1}, {b:2}]
call(*scores, {})
†有一个功能请求可以在Ruby 3中添加"真实"关键字参数。
‡ imo,使用call(*scores, **{})
指示"无关键字参数"将是更正确的,但是由于一个错误,目前这不起作用。但是,您可以使用call(*scores, **Hash.new)