Skip to content

Instantly share code, notes, and snippets.

@jhamon
Last active December 23, 2015 09:59
Show Gist options
  • Save jhamon/6618552 to your computer and use it in GitHub Desktop.
Save jhamon/6618552 to your computer and use it in GitHub Desktop.
## Mutable objects as hash keys: probably a bad idea.
silly_array = ['fox', 'cow', 'moose']
another_ref = silly_array
# These variable names refer to the same object
silly_array.object_id == another_ref.object_id # => true
# Even though it doesn't seem like a great idea,
# ruby will let us use mutable objects, like
# arrays, as keys in a hash.
silly_hash = { silly_array => 3 }
# Both variable names can be used as keys
silly_hash[silly_array] # => 3
silly_hash[another_ref] # => 3
# But other instances of array with equivalent values can
# also be used to access the hash, so the hash doesn't
# appear to care about the specific object being rerefenced.
imposter_array = ["fox", "cow", "moose"]
imposter.object_id == silly_array.object_id # => false
silly_hash[imposter] # => 3 ...still works fine.
# But bad things happen when we mutate the key object,
# and the key is changed in a way that suggests the specific
# object referenced as the hash key does have some role in
# the hash implementation.
silly_array.pop # => "moose"
silly_array # => ["fox", "cow"]
silly_hash # => {["fox", "cow"]=>3}
silly_hash[silly_array] # => nil
silly_hash.keys # => [["fox", "cow"]]
silly_hash[["fox", "cow"]] # => nil
# It seems we can no longer access the elements in the
# hash, by object reference or by value. Damn.
# Addendum: Turns out, there is a method that can help
# us recover from this problem.
silly_hash.rehash # => {["fox", "cow"]: 3}
silly_hash[["fox", "cow"]] # => 3 ...works again
silly_hash[silly_array] # => 3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment