当子元素不是数组时,SPLAT参数后需要的可选关键词参数

  • 本文关键字:参数 关键词 SPLAT 元素 数组 ruby
  • 更新时间 :
  • 英文 :


根据这篇文章,可以在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)

最新更新