Bug #19448
closed[Hash] Using Set as default value
Description
When using a hash and set is used as a default value, the keys method for the hash does not return expected values.
A workaround for this is provided in the attachment.
Files
Updated by byroot (Jean Boussier) almost 2 years ago
- Status changed from Open to Rejected
This isn't a bug and is documented in Hash.new
https://docs.ruby-lang.org/en/3.2/Hash.html#class-Hash-label-Default+Values
Note that the default value is used without being duplicated. It is not advised to set the default value to a mutable object:
synonyms = Hash.new([])
synonyms[:hello] # => []
synonyms[:hello] << :hi # => [:hi], but this mutates the default!
synonyms.default # => [:hi]
synonyms[:world] << :universe
synonyms[:world] # => [:hi, :universe], oops
synonyms.keys # => [], oops
To use a mutable object as default, it is recommended to use a default proc
Updated by Hanmac (Hans Mackowiak) almost 2 years ago
That's is known limitation when using Hash default value
Also your problem is that <<
would alter the same object you put into as default object
meaning:
h = Hash.new(Set.new)
h[:a] << 1
h[:b] << 2
p h[:c] #=> Set[1,2]
Updated by sawa (Tsuyoshi Sawada) almost 2 years ago
@byroot (Jean Boussier) (Jean Boussier), I think your comment is misleading if not irrelevant.
The issue's point is that, a key-value pair is not stored in the hash just by calling it. The relevant part in the example you cited is:
synonyms.keys # => [], oops
which is indeed not a bug.
To use a mutable object as default, it is recommended to use a default proc
is irrelevant/incomplete as a response to this issue because:
h = Hash.new{Set.new}
will not help. You have to explicitly store the key-value pair as in:
h = Hash.new{|hash, key| hash[key] = Set.new}
Updated by byroot (Jean Boussier) almost 2 years ago
@sawa (Tsuyoshi Sawada) I wasn't planning to answer the question myself, only to point the author to the detailed documentation of how Hash defaults works, so they can answer their own question.