in Python, a hash key cannot be [1,2,3] but must be (1,2,3), a tuple.
in Ruby, a list can actually be used as a hash key... but is it true
that it is using the list's ID as the key, not the list's content...
Not sure that this is true, since I don't understand what you mean.
(that's why in Python, tuples can be used as hash keys, since they are
unique by the values they contain)
what about in Ruby, since there is no tuple, how can you similate using
tuple as hash key? using list.join(",") as a key?
There's a better way. You can use just about any object as a key in a
ruby hash, but you need to be aware of a few key things.
1) Ruby hashes use two methods on a key to insert it or to search
for it. Those two methods are
hash and eql? Two objects are considered the same as far as the
hash is concerned if first
their hash values are equal, and second if they compare using
the :eql? method. When you
insert into a hash using a key, it's your responsibility to
ensure that if two objects are :eql? they
will return the same hash value. Ruby arrays (and most if not
all standard Ruby objects do)
2) In most cases Ruby hashes capture a reference to a key when it's inserted.
3) If you change an object which is referenced as a key in a hash in
such a way that it's hash
value changes, then the hash won't know about it without help,
and you'll likely be surprised.
Here's some code to walk through to illustrate the above:
# Make two different arrays, referenced by variables a and b respectively
a = [1, 2, 3]
b = [1, 2, 3]
# They are eql
a.eql? b # => true
# But not the same object
a.equal? b # => false
a.hash .eql? b.hash # => true
# Now create a hash using a as a key
h = {a => "Fred"}
# We can retrieve using the object referenced by a
h[a] # => "Fred"
# And using the variable referenced by b
h[b] # => "Fred"
# Or using an new literal array which is eql
h[[1,2,3]] # => "Fred"
# Note that a and b STILL refer to different objects
a.eql? b # => true
a.equal? b # => false
# Note also that hash.keys does not return the original object.
h.keys.first.eql? a # => true
h.keys.first.eql? b # => true
# Now lets change a
a << 4
# a and b should no longer be eql
a.eql? b # => false
# What happens if we access the hash now
h[a] # => nil
# And using the variable referenced by b
h[b] # => nil
# Or using an new literal array which is eql
h[[1,2,3]] # => nil
# What's happened is that the hash actually DID capture the key originally.
# The internal key changed so we can't find a value using [1,2,3]
# Notice that none of the above found a value even h[a], despite the
fact that a does
# in fact reference the new key:
a # => [1, 2, 3, 4]
# And we can't find it with an eql literal array either
h[[1,2,3,4]] # => nil
# The hash didn't know about the change to the key, so the hashing is
out of sync with reality
# Rehashing the hash rights things:
h.rehash
h[[1,2,3,4]] # => "Fred"
# So if we WANT to allow changing keys after putting them in a hash we
need to rehash after a change
# If we don't want to allow changing keys, then dup the key when you
put it in the hash.
h2 = {a.dup => "Ethel"}
h2[a] # => "Ethel"
a # => [1, 2, 3, 4]
h2[[1,2,3,4]] #=>
a << 5
# Since a has changed we don't expect to find it
h2[a] # => nil
# But since we duped it the key in the hash didn't change
h2[[1,2,3,4,5]] # => nil
h2[[1,2,3,4]] # =>
···
On 9/17/07, SpringFlowers AutumnMoon <summercoolness@gmail.com> wrote:
--
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/