在 Ruby 2.7 中,我可以有效地解构块参数中的哈希:
>> RUBY_VERSION
=> "2.7.6"
>> [{foo: 123}].each { |foo:| p foo }
123
=> [{:foo=>123}]
Run Code Online (Sandbox Code Playgroud)
在 Ruby 3.1 中,我不能:
>> RUBY_VERSION
=> "3.1.2"
>> [{foo: 123}].each { |foo:| p foo }
(irb):7:in `block in <top (required)>': missing keyword: :foo (ArgumentError)
Run Code Online (Sandbox Code Playgroud)
可以在参数列表之外对其进行模式匹配:
[{foo: 123}].each { |x| x => {foo:}; p foo }
Run Code Online (Sandbox Code Playgroud)
但如果可能的话,我正在寻找参数列表中的某些内容。
简短回答:不
each
只是将{foo: 123}
哈希值作为块参数传递,但 Ruby 3 期望foo:
传递实际的关键字。它相当于:
def m(foo:)
p foo
end
m({foo: 123})
# ArgumentError: wrong number of arguments (given 1, expected 0; required keyword: foo)
Run Code Online (Sandbox Code Playgroud)
您必须传递关键字参数或通过以下方式转换哈希**
:
m(foo: 123)
# 123
m(**{foo: 123})
# 123
Run Code Online (Sandbox Code Playgroud)
无论哪种方式,这都必须在调用方一侧“修复”。
在您的代码中,调用者是each
. 为了让您的代码正常工作,您可以定义自己的each
变体来执行所需的转换:
module Enumerable
def each_keyword
each { |hash| yield **hash }
end
end
Run Code Online (Sandbox Code Playgroud)
对于示例数据,其效果符合预期:
[{foo: 123}].each_keyword { |foo:| p foo }
# 123
Run Code Online (Sandbox Code Playgroud)
但是,我只是坚持each
并从传递的哈希中获取值:
[{foo: 123}].each { |h| p h[:foo] }
# 123
Run Code Online (Sandbox Code Playgroud)
如果你有一个散列,你可能应该将它视为一个。