Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent a positional argument from being expanded into keyword arguments?

I'd like to have a method that accepts a hash and an optional keyword argument. I tried defining a method like this:

def foo_of_thing_plus_amount(thing, amount: 10)
  thing[:foo] + amount
end

When I invoke this method with the keyword argument, it works as I expect:

my_thing = {foo: 1, bar: 2}
foo_of_thing_plus_amount(my_thing, amount: 20) # => 21

When I leave out the keyword argument, however, the hash gets eaten:

foo_of_thing_plus_amount(my_thing) # => ArgumentError: unknown keywords: foo, bar

How can I prevent this from happening? Is there such a thing as an anti-splat?

like image 371
ændrük Avatar asked Mar 18 '13 15:03

ændrük


People also ask

How do you fix positional arguments follows keyword arguments?

Using Positional Arguments Followed by Keyword Arguments One method is to simply do what the error states and specify all positional arguments before our keyword arguments! Here, we use the positional argument 1 followed by the keyword argument num2=2 which fixes the error.

Can positional arguments be used with keyword arguments?

Keyword arguments are passed to functions after any required positional arguments. But the order of one keyword argument compared to another keyword argument does not matter.

Can you use a mix of positional and keyword argument passing?

Unless otherwise specified, an argument can be both positional and keyword. Positional arguments, when provided, must be in sequence. Positional arguments must be used before keyword arguments.

What is meant by positional argument follows keyword argument?

The error positional argument follows keyword argument means that the if any keyword argument is used in the function call then it should always be followed by keyword arguments. Positional arguments can be written in the beginning before any keyword argument is passed.


2 Answers

This is a bug that was fixed in Ruby 2.0.0-p247, see this issue.

like image 126
Marc-André Lafortune Avatar answered Sep 23 '22 17:09

Marc-André Lafortune


What about

def foo_of_thing_plus_amount(thing, opt={amount: 10})
  thing[:foo] + opt[:amount]
end

my_thing = {foo: 1, bar: 2}   # {:foo=>1, :bar=>2}
foo_of_thing_plus_amount(my_thing, amount: 20)   # 21
foo_of_thing_plus_amount(my_thing)   # 11

?

like image 32
David Unric Avatar answered Sep 21 '22 17:09

David Unric