From ee1725cecb1c87ec10a8962ef8317610c5f989e4 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Tue, 11 May 2021 15:45:52 -0700 Subject: Update keyword argument description in method syntax guide Remove discussion of Ruby 2.7 specific handling of keyword argument separation. Add a small example of keyword to positional hash conversion for methods not accepting keyword arguments. --- doc/syntax/methods.rdoc | 86 ++++++------------------------------------------- 1 file changed, 9 insertions(+), 77 deletions(-) diff --git a/doc/syntax/methods.rdoc b/doc/syntax/methods.rdoc index b9ec8da5ff..e86cc2c00c 100644 --- a/doc/syntax/methods.rdoc +++ b/doc/syntax/methods.rdoc @@ -418,8 +418,8 @@ It is possible to gather arguments at the beginning or in the middle: gather_arguments 1, 2, 3, 4 # prints [2, 3] -The array argument will capture a Hash as the last entry if a hash was sent by -the caller after all positional arguments. +The array argument will capture a Hash as the last entry if keywords were +provided by the caller after all positional arguments. def gather_arguments(*arguments) p arguments @@ -491,83 +491,15 @@ 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 +If a method definition does not accept any keywords, and the +**nil syntax is not used, any keywords provided when calling +the method will be converted to a Hash positional argument: -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. - -In Ruby 2.7, 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 mandatory 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] + def meth(arg) + arg end - my_method(a: 1, 'a' => 2) # [{"a"=>2}, 1] - my_method({a: 1, 'a' => 2}) # [{"a"=>2}, 1] + meth(a: 1) + # => {:a=>1} === Block Argument -- cgit v1.2.3