Project

General

Profile

Actions

Misc #16645

closed

Non-warned change of behavior in 2.7 for non-symbol keys

Added by Dan0042 (Daniel DeLorme) about 4 years ago. Updated about 4 years ago.

Status:
Rejected
Assignee:
-
[ruby-core:97231]

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.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0