1

I have a piece of test code:

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) }

It generates a syntax error:

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

What is the correct way to call a block with a named parameter and an argument list? What is the idiomatic way to do this?

I also tried passing &block to test and doing block.call(state: :created, *args) with no luck.

1 Answer 1

3

You mixed up splat and double splat (note, that I changed all *args to **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 is used for unknown amount of plain params:

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

Double splat, introduced in Ruby2, is used to receive hash (named params):

def test a, b, **args
  puts args.inspect
end
test 42, true, hello: 'world'
#⇒ {:hello=>"world"}
Sign up to request clarification or add additional context in comments.

1 Comment

You are correct about the OP's mistake. But to be precise, that is not the direct cause of the syntax error (it would only cause an argument error). The reason for the syntax error is because named parameter (state: :created) was placed before *. However, what you pointed out is the indirect cause of the error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.