Copy constructors

Alex Martelli aleaxit at yahoo.com
Sun Aug 12 11:06:52 CEST 2001


"Guido van Rossum" <guido at python.org> wrote in message
news:cpwv4a9hwq.fsf at cj20424-a.reston1.va.home.com...
    ...
> > > That one seems to be related to _another_ capability (of which I've
> > > seen no indication that it's also going away) -- keeping the same
> > > class object. but changing that object (rebinding method attributes
> > > thereof).  Or maybe I don't understand exactly what you mean?
>
> As I just wrote, there will be two kinds of classes: immutable
> (static) classes and dynamic classes.  The latter can be modified just
> like classic ones.  But since this makes them less efficient, you have
> to be explicit about this (when using the new class mechanism, which
> is not the default in 2.2).

May I humbly suggest that this seems to be the same kind of design
error another great language designer, B. Stroustrup, made when he
decided that virtual methods (since they are less efficient) must be
explicitly specified as such, i.e. that the default for a C++ method
would be "non-overridable" (non-virtual).  Actually, I think Stroustrup
had more justification -- he was coming from a preliminary language
that had no virtual (no override) at all, and being able to generate very
fast code from a simple compiler was his number two design priority
(right after backwards compatibility with C, priority number one).  I
still believe that, despite this historical justification, in C++ as it
stands
today, having the optimization as the DEFAULT and having to be
explicit to TURN OFF the optimization is the wrong way 'round.  It
requires far too much foresight of the library designer to guesstimate
which methods may need to be overridden by library users, and the
need to explicitly say 'virtual' each and every time not-so-subtly
pushes AGAINST letting methods be overridable.

"Premature optimization is the root of all evil" (Kernighan, I believe).
Having generality as the default, and optimization explicitly requested,
seems to be a way to avoid *way-premature* optimization.  I do
realize that this, like all other generic considerations, needs to be
tempered with common sense, good taste, and design flair -- and
that you're past master at this and have repeatedly exhibited each
and every one of these admirable qualities.  I can think of cases in
Python where optimization is the default and things work fine, e.g.
local variables (although the optimization is _implicitly_ removed
by the presence of an exec statement, I guess you could classify
that as 'explicit' -- from the POV of the compiler it is, although from
that of a programmer, it 'just works').  But it seems to me that the
ability to change a class on the fly (and change an instance's class
to something different although "compatible") is very fundamental,
way more than the dirty tricks that would be enabled if local vars
weren't optimized, and quite comparable to a method being virtual.

COM Automation (MIDL) defaults any interface to being 'extensible'
(not a MIDL keyword, but you do have to explicitly specify the
'nonextensible' keyword for interfaces you want to be non-
dynamic).  This is typically surprising to programmers using it
with statically type-checked languages -- but Python's not going
down THAT route, is it?  With dynamic languages, extensibility of
an interface as the default is SO natural... the description of the
interface becomes a description of that subset of the interface that
is known at compile-time, so that optimization is possible for that
subset, but by default it remains possible to change it at runtime
(although methods outside of the compile-time subset will not be
anywhere as fast to call, since a general search-for-method becomes
necessary, that's OK).  If and when one needs absolute optimization
for an interface, THEN one explicitly optimizes by adding the
nonextensible attribute, so compilers can just insert the fast
method-lookup and give compile-time errors for methods that
are not listed in the now-known-to-be-immutable MIDL interface
description.  This allows natural-order development -- start with
a prototype of maximally dynamic nature, THEN, when the prototype
is working but too slow, get into the hairy issues of optimization,
including adding 'nonextensible' at suitable interfaces used in
hot-spots as shown by profiling (among many other optimization
techniques, of course).  Don't you want Python to support "get it
working, THEN make it fast" just as well in the future as it has in
the past...?


Alex






More information about the Python-list mailing list