1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Add documentation regarding keyword argument separation [ci skip]

This commit is contained in:
Jeremy Evans 2019-10-03 13:14:45 -07:00
parent 12e27a411c
commit c7715a4936
2 changed files with 97 additions and 1 deletions

View file

@ -279,6 +279,9 @@ hash at the end of the array into keyword arguments:
arguments = [1, 2, { c: 4 }] arguments = [1, 2, { c: 4 }]
my_method(*arguments) my_method(*arguments)
Note that this behavior is currently deprecated and will emit a warning.
This behavior will be removed in Ruby 3.0.
You may also use the <code>**</code> (described next) to convert a Hash into You may also use the <code>**</code> (described next) to convert a Hash into
keyword arguments. keyword arguments.
@ -325,7 +328,7 @@ by <code>*</code>:
Prints: Prints:
{:arguments=>[1, 2, {"3"=>4}], :keywords=>{:five=>6}} {:arguments=>[1, 2], :keywords=>{'3'=>4, :five=>6}}
=== Proc to Block Conversion === Proc to Block Conversion

View file

@ -436,6 +436,99 @@ for the keyword argument:
When mixing keyword arguments and positional arguments, all positional When mixing keyword arguments and positional arguments, all positional
arguments must appear before any keyword arguments. arguments must appear before any keyword arguments.
Also, note that <code>**</code> can be used to ignore keyword arguments:
def ignore_keywords(**)
end
To mark a method as accepting keywords, but not actually accepting
keywords, you can use the <code>**nil</code>:
def no_keywords(**nil)
end
Calling such a method with keywords or a non-empty keyword splat will
result in an ArgumentError. This syntax is supported so that keywords
can be added to the method later without affected backwards compatibility.
=== Keyword and Positional Argument Separation
Between Ruby 2.0 and 2.6, keyword and positional arguments were not
separated, and a keyword argument could be used as a positional argument
and vice-versa. In Ruby 3.0, keyword and positional arguments will
be separated if the method definition includes keyword arguments.
In Ruby 3.0, if the method definition does not include keyword arguments,
keyword arguments provided when calling the method will continue to be
treated as a final positional hash argument.
Currently, the keyword and positional arguments are not separated,
but cases where behavior will change in Ruby 3.0 will result in a
warning being emitted.
There are a few different types of keyword argument separation issues.
==== Conversion of Hash to Keywords
If a method is called with the hash, the hash could be treated as
keywords:
def my_method(**keywords)
keywords
end
my_method({a: 1}) # {:a => 1}
This occurs even if the hash could be an optional positional argument
or an element of a rest argument:
def my_method(hash=nil, **keywords)
[hash, keywords]
end
my_method({a: 1}) # [nil, {:a => 1}]
def my_method(*args, **keywords)
[args, keywords]
end
my_method({a: 1}) # [[], {:a => 1}]
However, if the hash is needed for a mandatory positional argument,
it would not be treated as keywords:
def my_method(hash, **keywords)
[hash, keywords]
end
my_method({a: 1}) # [{:a => 1}, {}]
==== Conversion of Keywords to Positional Arguments
If a method is called with keywords, but it is missing one
mandatory positional argument, the keywords are converted to
a hash and the hash used as the mandtory positional argument:
def my_method(hash, **keywords)
[hash, keywords]
end
my_method(a: 1) # [{:a => 1}, {}]
This is also true for empty keyword splats:
kw = {}
my_method(**kw) # [{}, {}]
==== Splitting of Positional Hashes or Keywords
If a method definition accepts specific keywords and not arbitrary keywords,
keywords or a positional hash may be split if the hash includes both Symbol
keys and non-Symbol keys and the keywords or positional hash are not needed
as a mandatory positional argument. In this case, the non-Symbol keys are
separated into a positional argument hash, and the Symbol keys are used
as the keyword arguments:
def my_method(hash=3, a: 4)
[hash, a]
end
my_method(a: 1, 'a' => 2) # [{"a"=>2}, 1]
my_method({a: 1, 'a' => 2}) # [{"a"=>2}, 1]
== Block Argument == Block Argument
The block argument is indicated by <code>&</code> and must come last: The block argument is indicated by <code>&</code> and must come last: