Bug #16473
closed
New deprecated warning disallows keyword arguments bypassing
Added by puchuu (Andrew Aladjev) almost 5 years ago.
Updated almost 5 years ago.
Description
Hello. I see that ruby 2.7.0 prints unnecessary deprecated warning during arguments bypassing.
def kw(a: 1)
puts "kw #{a}"
end
def non_kw(a = {}, *args)
puts "non kw #{a}"
kw *args
end
non_kw({ :a => 2 }, :a => 2)
non_kw({ :a => 3 })
non_kw
The right output is:
non kw {:a=>2}
kw 2
non kw {:a=>3}
kw 1
non kw {}
kw 1
Ruby 2.7.0 provides deprecated warning:
warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
*args
is bypassing arguments without any conversion. It looks like ruby converts last hash to keywords and than converts it back to hash. I think it is a bug.
- Subject changed from New deprecated warning disallows arguments bypassing to New deprecated warning disallows keyword arguments bypassing
- Status changed from Open to Rejected
This behavior is expected. The positional hash argument is converted to keyword arguments when kw
is called. That is not going to work in Ruby 3 (see #14183), hence the warning.
For delegating argument to a method that accepts keywords, you should probably use ruby2_keywords
(if you also need to support older ruby versions):
ruby2_keywords :non_kw if respond_to?(:ruby2_keywords, true)
@jeremyevans0 (Jeremy Evans), what will be the right way to bypass keyword arguments?
def non_kw(a = {}, **keyword_args)
puts "non kw #{a}"
kw **keyword_args
end
This variant is wrong with ruby 2, because it provides:
non kw {:a=>2}
kw 2
warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
warning: The called method `non_kw' is defined here
non kw {}
kw 3
non kw {}
kw 1
Will it work with ruby 3? Thank you.
puchuu (Andrew Aladjev) wrote:
@jeremyevans0 (Jeremy Evans), what will be the right way to bypass keyword arguments?
As mentioned earlier, you should probably use ruby2_keywords
. In this particular case, even if you don't want to support earlier Ruby versions, because you don't want the positional hash argument being interpreted as keywords by non_kw
.
In this particular case there would be a bug if *args
had more than one element, so I think the cleaner fix would be
def non_kw(a = {}, b = {})
puts "non kw #{a}"
kw **b
end
I really think the ruby2_keywords
workaround should be strictly reserved for cases where portability and generic delegation require it.
- Related to Feature #16463: Fixing *args-delegation in Ruby 2.7: ruby2_keywords semantics by default in 2.7.1 added
This is one clear case where #16463 would solve it intuitively.
Also available in: Atom
PDF
Like0
Like0Like0Like0Like0Like0Like0Like0