Why are tuples immutable?

Antoon Pardon apardon at forel.vub.ac.be
Wed Dec 22 06:14:15 EST 2004


Op 2004-12-22, Bengt Richter schreef <bokr at oz.net>:
> On 21 Dec 2004 10:37:20 GMT, Antoon Pardon <apardon at forel.vub.ac.be> wrote:
>
>>Op 2004-12-18, Bengt Richter schreef <bokr at oz.net>:
>>>>
>>>>As it turns out, python makes no difference in difficulty for making
>>>>either mutable or immutable objects usable as dictionary keys. The
>>>>only difference is that python only made its standard immutable
>>>>types hashable and not its standard mutable objects.
>>>>
>>> In one sense a mutable could looked upon as immutable until it is mutated,
>>> so why not allow its use in the same way as immutables?
>>> Is that basically the point of view you are trying to explain?
>>>
>>> Ok, suppose you did allow that. What kind of error symptoms would you like
>>> to have after a dict key is mutated and an attempt is made to look up the value
>>> using a mutable equal to the original key value? Presumably a KeyError exception?
>>> Or did you want to use a "frozen" copy of the original key, and not get a KeyError?
>>> Or should a new value equal to the mutated current value of the original key succeed?
>>
>>Why should we expect certain error symptoms? If you have sorted mutable
>>objects, mutated one element in the list and then apply an algorithm
>>that depended on the list to be sorted; would you then expect a
>>particular error symptom?

> It depends on the use of the sorted list, but the subject I was discussing was your requirements
> for a mutable-key dict. I was asking how you would like the mutable-key dict to behave
> IF a key was mutated and an attempt was made to retrieve the origninally stored value
> using a mutable key equal to the mutated value of the original key. E.g., if mkd is the mutable key dict,
>  key = [0]
>  mkd[key]=123
>  key[0] = 1
>  mkd[[1]] => ?
>
> I said I would go with the assumption that you would like it to succeed (return the 123 above).
> You said I assumed wrongly, but for some reason chose not to answer my questions or say what
> a "correct" assumption would be. Ok. If you're not interested in pursuing the "correct" version
> of the dict behavior _you_ were asking for, what are you interested in? ;-)

Well I think "like" is not the right word. Of course I would like that
it all magically repaired itself, but that is hardly a reasonable
expectation. To make it absolutly clear, I consider it a bug should
some code mutate a key in a dictionary (Under the provision that
the dictionary establishes a relationship between values, not
identities). I just find that countering such bugs by requiring keys to be
immutable is counterproductive. Sure advise people to use immutable keys
as much as possible. Caution people that should they use mutable keys
they should acertain themselves not to mutate such objects while they
are keys. But if a programmer finds that he needs a mutable object and
that it would be handy to use such an object as a key and he has some
assurance that those objects are stable while in use as a key, I see
nothing wrong with using such mutable objects as keys.

> In the above, I am in a position to detect some "errors," depending what _your_ specs are.
> I think it would be sloppy to let detectable errors pass silently, and in the case of mkd[[1]] above
> clearly it will succeed or not, depending on design. The logical thing would seem to be to
> return the matching value or design the dict so that mkd[[0]] would still retrieve 123 and
> mkd[[1]] would raise a KeyError. Either way, this is a particular error symptom to expect, because
> it is a direct consequence of a design decision. Your sorted list example does not say enough about
> the designed usage to say what specific errors might be expected, so it's not directly comparable.

I don't know if it is so logical to expect those kind of things. You
have meddled with the internals of the dictionary and IMO that means
all bets are off.

> If you are saying you are happy with "undefined behavior" as the outcome of mutating keys, ok,
> but if your implementation lets mutated-key errors pass silently, good luck debugging ;-)

But that problem is not limited to dictionaries. If you make a heapqueue
and mutate an element in it, such errors will pass silently too and 
will be just as hard to debug. Or suppose you create a class that
keeps a sorted list of a number of objects and the programmer accidently
mutates an object in it. That will probably pass silently too and
give you night mares debugging.

The problem is also that you really can't make new immutable objects
AFAIK. I have once made a vector class that didn't have any mutating
method and I always used it as if it as immutable but because of
the "we are all consenting adults here" attitude of python I can't
assure that other people of my class won't directly change a vector.

Do you find I shouldn't use these vectors as keys?

>>> Assuming the latter, what does this imply implementation-wise?
>>
>>You assume wrongly. I'm a bit sorry for that, because you obviously
>>spend time in this.
> That's ok, I made the choice ;-) I enjoy exploring ideas, and I thought it might
> be useful to help you explore the consequences of what you seemed to be asking for,
> and I was a bit curious how it would work out in practice when mutable keys were mutated.

Maybe this is some kind of misunderstanding, but I don't want mutating
keys. But the problem with immutable keys is that also the objects that
are not keys can't mutate.

Suppose you have some kind of latice, the elements of which you like to
use as keys. Now you want to know which elements along a path in this
latice are in the dictionary and that it is easy to mutate one element
in this path to the next, while it is more difficult to construct a
new next element from the old. Having immutable keys means that you
will have to use the more difficult construction path. You can't
have code as follows:

  point = start
  while point.IsFine():
    if point in some_dict:
      ...
    else:
      ...
    point.Move_To_Next()


> I obviously could have made it work differently, and was trying to guess what alternative
> you might be interested in. ISTM from the little experiment I posted in this thread that
> mutable keys for dicts is fraught with pitfalls even if you intend never to mutate keys
> in use, because of the potential for silent bugs if you accidentally do. But perhaps something
> useful can be designed, if design decisions are carefully made.

But mutable objects is fraught with pitfall anyhow. Even mutating an
element in a list you are iterating over can give unexpected results
or just assigning a mutable to other names a few times and then mutating
it through one name and finding out an other name that was supposed to
stay stable, mutated too. Why else the warning against the use of
a default value of [] for an argument?

> If you enjoy exploring ideas too, you might get even more enjoyment by participating
> more directly. E.g., at this point you might have volunteered to mention what would have
> been a "correct" assumption to make in place of the one you say I made wrongly.

Well the only suggestion I would make now is that it would be nice to
have a second dict type that would make a copy of a key and insert
that copy in the dictionary. That would already protect against a
lot of unintentional key mutating for people who would find it usefull
to use mutables as keys.

Maybe a dictionary that would pickle and unplickle keys as needed.
That would make keys immutable while the objects are not, but
this would be with at a performance loss. But such a loss may be
acceptable and if not the dict could still be usefull for debugging
purposes.

A last idea, but this definetly is only usefull for debugging, is
having a dictionary that keeps a copy of the key, with the ability
to check the keys againt the copy, this might help in debugging.

> Your reticence does make me wonder what you consider to be rewarding about participating
> in this kind of thread ;-) Cruel rejection is not the style of c.l.py,

I'm not so certain about that. Of course it depends on when you start
calling something cruel. But while contributing on c.l.py I have been
called a troll because of some misunderstanding about python while
that person's previous message seemed to propagate the misunderstanding.
I have been told to search for an other languange because I thought
certain things in python are warts and others seem to think my
critisizing some aspects of the language is inappropiate because they
seem to equate it with a demand from me for a change in the immediate future
or people who think that because I find there defense of a certain
feature weak, who think I want to get rid of the feature.

Personnaly I find the atmosphere in general here very defensive when
some kind of feature is questioned. There seems a definite "Love it
or leave it" attitude to be present.

> but if you have
> had such experience, somewhere, bringing that baggage with you into the present in search
> of resolution is likely to limit your new experiences to something less than an optimally
> pleasant dialog ;-) The kids here mostly play nice ;-)

I have usenet experience enough to know that newsgroups can vary wildly
and that you should evaluate each on its own merits. I do agree c.l.py
is very helpfull in case you need help in how to solve a particular
problem in the language. That niceness can disappear rather swiftly
if the pros and cons of python itself get discussed.


>>> Hm, just for the heck of it, does this do what you want? (all features not tested, none tested beyond what you see,
>>> and special methods like update and iterators will just work on the plain dict part if they work at all, unless
>>> you add the code ;-)
>>
>>I don't expect anyting special. Python provides all that is needed. It
>>is just that the documentation suggests otherwise.
>>
> So is there anything you would like to do to help make things better
> for yourself and everyone? ;-)

I'm currently not under the impression I'm able to. Sure I could
implement the above mentioned classes, but my feeling is that
should I present them here, nobody would be waiting for them.
Not because they would be unusfull, but because they go against
the current paradigm.

-- 
Antoon Pardon



More information about the Python-list mailing list