Project

General

Profile

Actions

Bug #16498

closed

Hash#transform_values in 2.7.0 sets new hash's default to old hash's default_proc

Added by ptsengineer (Peter Tsengineer) over 2 years ago. Updated almost 2 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
[ruby-core:96759]

Description

The following is unexpected for me.

Hash.new { }.transform_values { }.default
# => #<Proc:0x000055eecda01510 -e:1>
Hash.new { }.transform_values { }[:any]
# => #<Proc:0x0000563a12e35510 -e:1>
Hash.new { :default }.transform_values { }[:any][]
# => :default

I did not think a default_proc would turn into a default. The previous behaviour in 2.6 was that the default would be nil, so this is new in 2.7. But I didn't see this mentioned in the 2.7 NEWS. May I learn of the proper use for this and/or whether it is intentional?

If you wonder when we might see something like this, I had found it with code similar in idea to the following:

weights = Hash.new { |h, k| h[k] = [] }
weights[:apple] << 1
weights[:apple] << 2

prices = weights.transform_values { :arbitrary }

puts (prices[:mango] || [])[0] || "We're all out of mangoes today"
in `block in <main>': undefined method `[]=' for 0:Integer (NoMethodError)

That was quite a confusing error message. It took a while to realise why []= was called on 0.

We also cannot fix this by using dig (puts prices.dig(:mango, 0) || "We're all out of mangoes today") because then, we would get:

in `dig': Proc does not have #dig method (TypeError)

Related issues 1 (0 open1 closed)

Has duplicate Ruby master - Bug #16914: Hash.new with `default_proc` returns this `default_proc` instead of calling it sometimesClosedActions
Actions #1

Updated by ptsengineer (Peter Tsengineer) over 2 years ago

  • Description updated (diff)
Actions #2

Updated by ptsengineer (Peter Tsengineer) over 2 years ago

  • Subject changed from Hash#transform_value in 2.7.0 sets new hash's default to old hash's default_proc to Hash#transform_values in 2.7.0 sets new hash's default to old hash's default_proc
Actions #3

Updated by ptsengineer (Peter Tsengineer) over 2 years ago

  • Description updated (diff)
Actions #4

Updated by sawa (Tsuyoshi Sawada) over 2 years ago

  • Description updated (diff)
Actions #5

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

  • Status changed from Open to Closed

Applied in changeset git|1b4d406e3a04032b6d01e92b6d184a16945c6ac3.


Hash#transform_values should return a plain new Hash

[Bug #16498]

Updated by vo.x (Vit Ondruch) about 2 years ago

  • Backport changed from 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN to 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: REQUIRED

This does break ActiveSupport 5.2 test suite.

Actions #7

Updated by nobu (Nobuyoshi Nakada) almost 2 years ago

  • Related to Bug #16914: Hash.new with `default_proc` returns this `default_proc` instead of calling it sometimes added
Actions #8

Updated by nobu (Nobuyoshi Nakada) almost 2 years ago

  • Related to deleted (Bug #16914: Hash.new with `default_proc` returns this `default_proc` instead of calling it sometimes)
Actions #9

Updated by nobu (Nobuyoshi Nakada) almost 2 years ago

  • Has duplicate Bug #16914: Hash.new with `default_proc` returns this `default_proc` instead of calling it sometimes added
Actions #10

Updated by nobu (Nobuyoshi Nakada) almost 2 years ago

  • Backport changed from 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: REQUIRED to 2.5: DONTNEED, 2.6: DONTNEED, 2.7: REQUIRED

Updated by nagachika (Tomoyuki Chikanaga) almost 2 years ago

  • Backport changed from 2.5: DONTNEED, 2.6: DONTNEED, 2.7: REQUIRED to 2.5: DONTNEED, 2.6: DONTNEED, 2.7: DONE

ruby_2_7 05c4c88767b54808cd1459a1d6da11179c422cfa merged revision(s) 1b4d406e3a04032b6d01e92b6d184a16945c6ac3.

Actions

Also available in: Atom PDF