在块调用中传递命名参数和可变数量的参数

Passing named arguments and variable number of arguments in block call

我有一段测试代码:

def asdf(id: nil, field: nil, state: nil)
  puts "id: #{id}, field: #{field}"
end

def test(a, b, *args)
  # a, b are needed only inside #test
  yield(state: :created, *args)
end

test('a', 'b', id: 'xyz', field: :asd) { |*args| asdf(*args) }

它产生语法错误:

syntax error, unexpected *
yield(state: :created, *args)

使用命名参数和参数列表调用块的正确方法是什么?执行此操作的惯用方法是什么?

我也试过将 &block 传递给 test 并执行 block.call(state: :created, *args) 但没有成功。

你混淆了 splat 和 double splat(请注意,我将所有 *args 更改为 **args):

def asdf(id: nil, field: nil, state: nil)
  puts "id: #{id}, field: #{field}"
end

def test(a, b, **args)
  # a, b are needed only inside #test
  yield(state: :created, **args)
end

test('a', 'b', id: 'xyz', field: :asd) { |**args| asdf(**args) }
#⇒ id: xyz, field: asd

Splat 用于未知数量的 plain 参数:

def test a, b, *args
  puts args.inspect
end
test 42, true, 'additional'
#⇒ ["additional"]

Ruby2中引入的double splat,用于接收hash(named params):

def test a, b, **args
  puts args.inspect
end
test 42, true, hello: 'world'
#⇒ {:hello=>"world"}