Issue #14380 has been updated by rafaelfranca (Rafael Frana).


> change will also be applied in ActiveSupport

Where did you get that information?

This change silently breaks applications when upgrading to 2.6 version. Backward compatibility not only with active support but with an already released version of Ruby should be took in consideration here.

I don't think the Rails team would accept this change as a bug fix.

----------------------------------------
Bug #14380: Expected transform_keys! to work just as transform_keys, but it doesn't
https://bugs.ruby-lang.org/issues/14380#change-71126

* Author: taw (Tomasz Wegrzanowski)
* Status: Closed
* Priority: Normal
* Assignee: matz (Yukihiro Matsumoto)
* Target version: 
* ruby -v: ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin17]
* Backport: 2.3: DONTNEED, 2.4: DONTNEED, 2.5: REQUIRED
----------------------------------------
This seriously violates the Principle of Least Surprise to me:

    {1 => :a, -1 => :b}.transform_keys{|k| -k} #=> {-1=>:a, 1=>:b}
    {1 => :a, -1 => :b}.transform_keys!{|k| -k} # => {1=>:a}

    # This fails:
    ht=(1..10).map{|k| [k,k]}.to_h; ht.transform_keys(&:succ) # => {2=>1, 3=>2, 4=>3, 5=>4, 6=>5, 7=>6, 8=>7, 9=>8, 10=>9, 11=>10}
    ht=(1..10).map{|k| [k,k]}.to_h; ht.transform_keys!(&:succ) # => {11=>1}

    # This code with same issue works just because of key ordering:
    ht=(1..10).map{|k| [k,k]}.to_h; ht.transform_keys(&:pred) #=> {0=>1, 1=>2, 2=>3, 3=>4, 4=>5, 5=>6, 6=>7, 7=>8, 8=>9, 9=>10}
    ht=(1..10).map{|k| [k,k]}.to_h; ht.transform_keys!(&:pred) #=> {0=>1, 1=>2, 2=>3, 3=>4, 4=>5, 5=>6, 6=>7, 7=>8, 8=>9, 9=>10}

Of course in these examples it's very easy to see the problem, but in bigger programs it could be really difficult.

If the implementation instead did equivalent of:

    class Hash
      def transform_values!(&block)
        replace transform_values(&block)
      end
    end

it would be much less surprising.

`Hash#transform_keys` / `Hash#transform_keys!` inherently require that resulting values don't collide, but in these examples it works in surprising ways even though there's no collision between results.



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

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