Qualified appology (was Re: anything like C++ references?)

Stephen Horne intentionally at blank.co.uk
Sun Jul 13 22:24:28 EDT 2003


Appols for changing the subject while still staying in the same topic
- I just wanted to highlight this over my earlier boneheaded posts.

This is a post of heavily qualified appologies. In summary, I've been
thick-headed but I still believe that Python is doing the wrong thing.

I hope I've actually achieved a degree of sanity on this attempt ;-)


On 14 Jul 2003 00:17:19 +0200, martin at v.loewis.de (Martin v. Löwis)
wrote:

>Stephen Horne <intentionally at blank.co.uk> writes:
>
>> 1.  Why are dictionarys called dictionaries (rather than references to
>> dictionarys or whatever)? Similar for lists and class instances.
>
>Because they are the values themselves, instead of being references to
>values. These values (like all other values) are objects, though,
>which means they have identity, state, and behaviour.

I've said my piece on meanings derived from computer science (and in
turn from mathematics, as it happens - variables as placeholders for
values predate electronic computers by quite some time.

People have tried to point out that copy-on-write is redundant for
immutable objects, but I've been too thick-headed. Sorry for that.

Even so, you can think of immutable objects as achieving 'expected'
assignment semantics simply because they are immutable. That does not
apply to mutable objects. So you can claim that Python behaviour is
consistent within itself, but only by claiming that it is consistently
different from this 'expected' behaviour.

Some people have already said that the word 'expected' is a fallacy -
that computer science doesn't have fixed definitions for these things.
Some have already named various languages which deviate in similar
ways in either some or all cases. But these languages are actually
deviating, either by convention or (in older cases) due to the
limitations of past machines. That's not the same thing as saying they
are doing 'the right thing' or that the computer science definitions
don't exist - all it means is that a lot of programmers who are
experienced in certain languages are familiar with this error-prone
system and used to compensating for its problems. But a modern
high-level language should do 'the right thing' - it should not be the
programmers job to make allowances for an outdated workaround designed
to give maximum performance by default on old machines irrespective of
reliability.

>> 2.  Why are the values of mutable objects always forced to be accessed
>> via a pointer (or reference or whatever)?
>
>Because all variables are references to objects.

All variables are implemented as references, but that is not the same
as saying that all values are references. As Guidos own words reveal
(I already posted the link twice) the purpose of using immutables
tuples is performance optimisation to save copying while still
defending against against accidental mutation (ie it provides the
computer theory standard assignment semantics efficiently).

The same rationale should equally apply to all types, including the
mutable types.

In particular, it should apply to class instances. I shouldn't need to
create separate mutable and immutable variants of classes to get this
as the mutability of content should be the decision of the container
rather than the content. I shouldn't need to force copying of class
instances in the container for the exact same reason that Guido
highlights for tuples.

Guidos own example is actually quite bug prone in its own way. It
behaves differently depending on whether you pass in the point values
as tuples or lists. That is potentially a subtle, intermittent,
hard-to-trace error waiting to happen. You can say 'validation' all
you want. I did that back in the PEP238 days, and didn't get much
support. What's good for the goose is good for the gander.

>> This excuse is, as I already said, invalid.
>
>Which excuse? You have only listed questions in this message, not
>excuses.

Looking back, I was unfair to Tim Peters. The 'excuse' was percieved
(mainly because I'm frustrated trying to get my point across, and
because a circularity that arose (unless I was thick-headed about that
too) in another post. I said 'if a then b', someone said 'no - a is
wrong because c', I said 'ah, but if c then d' and the reply to that
was 'no - c is wrong because a' - or at least I think that's what
happened. Possibly I just need some sleep.

I thought Tim was also guilty of this, but looking back I was wrong.
Sorry, Tim.

However, revisiting his post I still disagree with it...

"""
It's deliberate and thoroughly consistent.  Any assignment semantics
are
error-prone in some contexts, though (Python's included -- side
effects are
like that).  The simplicity and absolute consistency of Python-style
assignment semantics are probably easiest for first-time programmers
to pick
up, and certainly dead easy for people coming from Lisp (etc) to pick
up --
people coming from C (etc) often struggle with inappropriate
expectations at
first.
"""

At first glance it looked like Tim was saying 'its all assignment
semantics rather than type semantics', hence my misjudging him. But
one way or the other, there is an inconsistency between the behaviour
of mutable objects and the computer science definitions of 'variable',
'value' and 'assignment' which does not arise for immutable objects
(note careful wording - see earlier apology). Having copy-on-write for
all objects (obviously the actual copying never happening for
immutables) would be both fully self-consistent and consistent with
the computer science definitions. The lack of this definitely does
cause both confusion and errors.

I also disagree with Tims statement that "Any assignment semantics are
error-prone in some contexts". OK, mistakes can be made with any
syntax for anything, but in the context of this discussion it is
perfectly possible to get the best of both worlds.

Make pointers/references explicit and make all assignments
'copy-on-write', and as I said earlier you get both mutability
protection by default for all types and the ability to reference any
type indirectly. Avoid the problems that make pointers in C, C++,
Pascal etc so unreliable and, while perceptions of pointers as being
inherently bug prone may persist they would be irrational - having
pointers explicitly for all types would at worst be as bug prone as
the existing situation where implicit references exist, and in
particular where mutable types get abused to fake pointer/reference
capabilities. It needs extra notation, but when mutables are used to
fake pointers there is extra notation anyway - misleading notation.

I'm not an anti-side-effect fanatic. I just don't want them to happen
by default, and I don't have to worry about this every time I use a
mutable type. And there really is no need for that to happen.





More information about the Python-list mailing list