It's quite expected because the default array is created exactly once:
letters = Hash.new([])
letters.default.object_id # => 70310393550400
letters[:a].object_id # => 70310393550400
letters[:b].object_id # => 70310393550400
The pattern that Arvinder wants is:
letters = Hash.new { |h, k| h[k] = [] }
letters.default # => nil
letters.default_proc # => #Proc:0x007fe4d4099988@(irb):7
letters[:a].object_id # => 70310393174180
letters[:b].object_id # => 70310393171680
It's possible to make the correct pattern do the "wrong thing":
array = []
array.object_id # => 70310393550400
letters = Hash.new { |h, k| h[k] = array }
letters.default # => nil
letters.default_proc # => #Proc:0x007fe4d4099988@(irb):7
letters[:a].object_id # => 70310393550400
letters[:b].object_id # => 70310393550400
-a
On Wed, Jan 7, 2015 at 8:16 PM, duerst@it.aoyama.ac.jp wrote:
Issue #10713 has been updated by Martin Dürst.
Hiroshi SHIBATA wrote:
It's expected behavior
Hiroshi, can you tell us why it's expected behavior? It looks quite
surprising.
Bug #10713: Assigning default value for a Hash as an empty Array creating
unpredictable results
https://bugs.ruby-lang.org/issues/10713#change-50846
- Author: Arvinder Singh
- Status: Rejected
- Priority: Normal
- Assignee:
- Category: core
- Target version: current: 2.2.0
- ruby -v: ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin14]
- Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN
Creating a Hash with a default value works fine, unless the default value
is an empty Array.
E.g. the following returns an empty Hash...
irb(main):001:0> letters = Hash.new([])
=> {}
irb(main):002:0> letters[:a] << 1
=> [1]
irb(main):003:0> letters[:a] << 2
=> [1, 2]
irb(main):004:0> letters[:a]
=> [1, 2]
irb(main):005:0> letters
=> {}
whereas the following code explicitly defining hash keys works.
irb(main):001:0> letters = {a: [], b: []}
=> {:a=>[], :b=>[]}
irb(main):002:0> letters[:a] << 1
=> [1]
irb(main):003:0> letters[:a] << 2
=> [1, 2]
irb(main):004:0> letters[:a]
=> [1, 2]
irb(main):005:0> letters
=> {:a=>[1, 2], :b=>[]}
Is this an unpredictable(bug) or an expected behavior(feature). I tend to
lean towards the former, but I might be wrong.
--
https://bugs.ruby-lang.org/
--
Austin Ziegler * halostatue@gmail.com * austin@halostatue.ca
http://www.halostatue.ca/ * http://twitter.com/halostatue