Mike C. Fletcher mcfletch at rogers.com
Tue Feb 24 22:30:50 CET 2004

```Marco Aschwanden wrote:
...

>Maybe I don't get the point here: Why do dictionaries need tuples to
>work? I know that tuples can be used as keys... but how many times do
>you need tuples as dictionary keys (it would be simple to turn a list
>into an immutable string if really needed ("::".join(["a","b"]). But
>maybe tuples are used within dictionary in a way I don't know. If you
>could clarify on this point I will never ever say anything about
>dictionaries" 8o)
>
>
x = [1,2]
d = { x : 32 }
x.append( 3 )
d[ [1,2] ]

Does that last line raise a key-error, or return 32?  Tuples are useful
as keys precisely because they are immutable, and hash based on their
contents/value.  Mutable keys in dictionaries either need to be
"identity" based (which is far less useful that "value" based, (as then
you can only test whether a particular list is used as a key, not any
list with the same value)), or have some funky book-keeping rules
regarding what happens when the key changes (for example, convert the
key to a tuple under the covers so that all further changes to the key
are ignored in the dictionary).

To clarify regarding identity:

x = (1,2)
d = { x : 32 }
d[ x ]
d[ (1,2) ]

because they hash and compare based on value, tuples here can
unambiguously be used as value-based keys.  With a list, were we to use
identity-based comparisons:

x = [1,2]
d = { x : 32 }
d[ x ] # would return a value
d[ [1,2] ] # would raise a key-error,
# defeating one of the most common usage patterns for
tuples-in-dictionaries

while if we were to use value-based comparisons set at key-specification
time:

x = [1,2]
d = { x: 32 }
x.append( 3 ) # possibly done in another thread...
del d[ x ] # would raise a key-error

to do lots of common operations (such as iterating through the keys of a
dictionary and deleting those which meet a particular test) in this
scenario you'd need to be able to return a static key in order to be
sure not to have it mutate while you're working, so you'd need an
exposed list-like immutable data-type (sound familiar).

Now, as shown above, we could do an explicit cast on setting a
dictionary value to make a list a tuple "under the covers" and thus get
back... but this is another "explicit is better than implicit" things.
The magic would up and bite in debugging weird corner cases more times
than it saved you a few seconds of thinking in the design stage.  We
still have the static type, it would need to be dealt with in code, and
it would be surprising to see it show up instead of the lists we
originally used as the keys.

Using lists forced to strings would be a difficult sell even without the
problems described above, particularly as you can quite readily have
strings as keys already, so you get difficult-to-debug collisions where
a string just happens to equal the string-ified list representation of
some other value.  The "explicit is better than implicit" axiom of
"import this" would then suggest that having an explicitly defined
immutable type (tuple) that hashes by value and is used to set keys in a
dictionary is a better choice than automagically coercing the lists to a
hidden type (or a string).

Don't worry about asking questions like this, by the way, it's good for
the perceptions of the community to be stirred every once in a while.
Enjoy yourself,
Mike

_______________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://members.rogers.com/mcfletch/

```