Misc #16645
closedNon-warned change of behavior in 2.7 for non-symbol keys
Description
In ruby 2.7 non-symbol keys are now accepted as keywords, resulting in the following change in behavior:
def foo(*a,**h) p [a,h] end
foo("a"=>42)
# [[{"a"=>42}], {}] in 2.6
# [[], {"a"=>42}] in 2.7
Given that the general plan for 2.7 was to be backward compatible while warning about upcoming changes, I just wanted to confirm if it was ok to change this without a deprecation phase? I couldn't find any reference or discussion about this in the dev meeting logs.
Updated by shevegen (Robert A. Heiler) about 4 years ago
I can not answer your question but I believe matz mentioned the change several times in different
talks before. So a deprecation phase makes no real sense, unless matz and the core team wants
to postpone the change past ruby 3.0 - but I think it was decided that keyword arguments will be
just about the only backwards incompatible change before. If you look at the issue tracker,
you will always have people who want more deprecations and more changes, and people who want
less - e. g. the discussion about frozen strings by default, where headius (and probably others)
would like a change in ruby 3.0 already. ;) (It's a decision either way and I think for keywords
the decision has already been made months before to change this in 3.0, so a deprecation phase
would make no real sense to me, IMO, in this regard.)
Updated by jeremyevans0 (Jeremy Evans) about 4 years ago
- Status changed from Open to Rejected
Yes, treating non-Symbol keys as keywords if the method accepts arbitrary keywords is expected behavior, as mentioned in the Ruby 2.7.0 release notes (https://www.ruby-lang.org/en/news/2019/12/25/ruby-2-7-0-released/). This is a deliberate change from previous versions.
There are various related cases using non-arbitrary keywords or hashes where Ruby will warn and treat this as a positional argument:
def a(*a, b: 1)
[a, b]
end
a("a"=>1)
# (irb):2: warning: Passing the keyword argument as the last hash parameter is deprecated
# (irb):1: warning: The called method `a' is defined here
# => [[{"a"=>1}], 1]
a("a"=>1, b: 1)
# (irb):3: warning: Splitting the last argument into positional and keyword parameters is deprecated
# (irb):1: warning: The called method `a' is defined here
# => [[{"a"=>1}], 1]
a({"a"=>1})
# => [[{"a"=>1}], 1
# No warning or attempt to convert to keywords
Updated by Dan0042 (Daniel DeLorme) about 4 years ago
treating non-Symbol keys as keywords if the method accepts arbitrary keywords is expected behavior
Yes, I was aware of that, it's just that I always thought of this as simply an additional behavior; previously **hash
would raise an error if it contained non-symbol keys and now it doesn't. I've tried to stay up to date on the keyword separation development, but until now it never occured to me this particular feature could cause regressions. Oh well, at this point second thoughts about compatibility are pretty much pointless.