Issue #14183 has been updated by jeremyevans0 (Jeremy Evans). koic (Koichi ITO) wrote: > Thank you very much. It is solved by `**h`. > However, in the following complicated case, it seems difficult to solve u= sing `**h`. This is an interesting use case :-) > = > ```ruby > def do_something(*args, &block) > yield 'yield_self', {expected: 'then'} > end > = > do_something do |code, expected:, use: expected, instead_of: code| > puts "code: =A0 =A0 =A0 #{code}" > puts "expected: =A0 #{expected}" > puts "use: =A0 =A0 =A0 =A0#{use}" > puts "instead_of: #{instead_of}" > end > ``` Unless I'm missing something, it should be sufficient to drop the braces in= the yield, so you are calling the block with keywords instead of a hash: ```ruby def do_something(*args, &block) yield 'yield_self', expected: 'then' end ``` This will still work correctly if the block accepts a hash argument instead= of keywords. ---------------------------------------- Feature #14183: "Real" keyword argument https://bugs.ruby-lang.org/issues/14183#change-83095 * 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>