Issue #14183 has been updated by koic (Koichi ITO).


Thank you very much. It is solved by `**h`.
However, in the following complicated case, it seems difficult to solve usi=
ng `**h`. This is an interesting use case :-)

```ruby
# example.rb
def do_something(*args, &block)
=A0 yield 'yield_self', {expected: 'then'}
end

do_something do |code, expected:, use: expected, instead_of: code|
=A0 puts "code: =A0 =A0 =A0 #{code}"
=A0 puts "expected: =A0 #{expected}"
=A0 puts "use: =A0 =A0 =A0 =A0#{use}"
=A0 puts "instead_of: #{instead_of}"
end
```

```
% ruby exmaple.rb/tmp/foo.rb:2: warning: The last argument is used as the k=
eyword parameter
/tmp/foo.rb:5: warning: for `false' defined here; maybe ** should be added =
to the call?
code: =A0 =A0 =A0 yield_self
expected: =A0 then
use: =A0 =A0 =A0 =A0then
instead_of: yield_self
```

I think it will be solved by converting from hash to kwarg. But it can be c=
omplicated to solve when implemented by several different libraries.

I met this usage in real-world code.=A0I show it as a use case with block a=
rguments.
https://github.com/rubocop-hq/rubocop/blob/v0.77.0/spec/rubocop/cop/style/n=
umeric_predicate_spec.rb#L12

----------------------------------------
Feature #14183: "Real" keyword argument
https://bugs.ruby-lang.org/issues/14183#change-83080

* Author: mame (Yusuke Endoh)
* Status: Closed
* Priority: Normal
* Assignee: =

* Target version: Next Major
----------------------------------------
In RubyWorld Conference 2017 and RubyConf 2017, Matz officially said that R=
uby 3.0 will have "real" keyword arguments.  AFAIK there is no ticket about=
 it, so I'm creating this (based on my understanding).

In Ruby 2, the keyword argument is a normal argument that is a Hash object =
(whose keys are all symbols) and is passed as the last argument.  This desi=
gn is chosen because of compatibility, but it is fairly complex, and has be=
en a source of many corner cases where the behavior is not intuitive.  (Som=
e related tickets: #8040, #8316, #9898, #10856, #11236, #11967, #12104, #12=
717, #12821, #13336, #13647, #14130)

In Ruby 3, a keyword argument will be completely separated from normal argu=
ments.  (Like a block parameter that is also completely separated from norm=
al arguments.)
This change will break compatibility; if you want to pass or accept keyword=
 argument, you always need to use bare `sym: val` or double-splat `**` synt=
ax:

```
# The following calls pass keyword arguments
foo(..., key: val)
foo(..., **hsh)
foo(..., key: val, **hsh)

# The following calls pass **normal** arguments
foo(..., {key: val})
foo(..., hsh)
foo(..., {key: val, **hsh})

# The following method definitions accept keyword argument
def foo(..., key: val)
end
def foo(..., **hsh)
end

# The following method definitions accept **normal** argument
def foo(..., hsh)
end
```

In other words, the following programs WILL NOT work:

```
# This will cause an ArgumentError because the method foo does not accept k=
eyword argument
def foo(a, b, c, hsh)
  p hsh[:key]
end
foo(1, 2, 3, key: 42)

# The following will work; you need to use keyword rest operator explicitly
def foo(a, b, c, **hsh)
  p hsh[:key]
end
foo(1, 2, 3, key: 42)

# This will cause an ArgumentError because the method call does not pass ke=
yword argument
def foo(a, b, c, key: 1)
end
h =3D {key: 42}
foo(1, 2, 3, h)

# The following will work; you need to use keyword rest operator explicitly
def foo(a, b, c, key: 1)
end
h =3D {key: 42}
foo(1, 2, 3, **h)
```

I think here is a transition path:

* Ruby 2.6 (or 2.7?) will output a warning when a normal argument is interp=
reted as keyword argument, or vice versa.
* Ruby 3.0 will use the new semantics.

---Files--------------------------------
vm_args.diff (4.19 KB)
vm_args_v2.diff (4.18 KB)


-- =

https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=3Dunsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>