我可以在Ruby 3.1中解构块参数中的散列吗?|食物:|`?

4nkexdtk  于 2022-12-22  发布在  Ruby
关注(0)|答案(3)|浏览(88)

在Ruby 2.7中,我可以有效地解构块参数中的散列:

>> RUBY_VERSION
=> "2.7.6"
>> [{foo: 123}].each { |foo:| p foo }
123
=> [{:foo=>123}]

在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)
  • 有 * 可能在参数列表 * 之外 * 对其进行模式匹配:
[{foo: 123}].each { |x| x => {foo:}; p foo }

但如果可能的话,我会在参数列表 * 中寻找一些东西。

am46iovg

am46iovg1#

简短回答:没有
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)

您必须传递关键字参数或通过**转换散列:

m(foo: 123)
# 123

m(**{foo: 123})
# 123

无论哪种方式,这都必须在调用方一侧"固定"。
在你的代码中,调用者是each。为了让你的代码正常工作,你 * 可以 * 定义你自己的each变量来完成所需的转换:

module Enumerable
  def each_keyword
    each { |hash| yield **hash }
  end
end

对于示例数据,其工作方式与预期相同:

[{foo: 123}].each_keyword { |foo:| p foo }
# 123

不过,我还是坚持使用each,并从传递的散列中获取值:

[{foo: 123}].each { |h| p h[:foo] }
# 123

如果你有一个散列,你可能应该把is当作一个散列。

nhaq1z21

nhaq1z212#

关键字参数处理的差异:

# 2.7
>> [{foo: 123}].each {|*args, **kwargs| puts "args=#{args}, kwargs=#{kwargs}" }
args=[], kwargs={:foo=>123}

# 3.1
>> [{foo: 123}].each {|*args, **kwargs| puts "args=#{args}, kwargs=#{kwargs}" }
args=[{:foo=>123}], kwargs={}
# NOTE: no kwargs, no match.

我能找到的最接近的:

>> [{foo: 1},{foo: 2}].each { _1 => foo:; p foo }
1
2

# in the parameter list
>> [{foo: 1},{foo: 2}].each { |i, foo: i[:foo]| p foo }
1
2
f4t66c6m

f4t66c6m3#

在ruby 3中,我们可以使用向右赋值来解构:

[{foo: 123}, {foo: 222}].each {|h| h=> {foo:}; p foo}
123
222                                                 
 => [{:foo=>123}, {:foo=>222}]

注意:foo将在每次迭代时分配新值

相关问题