[Python-Dev] succinctness? (was: Extended Function syntax)

Alex Martelli aleax@aleax.it
Mon, 3 Feb 2003 15:05:14 +0100


On Monday 03 February 2003 01:05 pm, Samuele Pedroni wrote:
   ...
> does what iterclose does a bunch of times in program, she could be tempted
> to write iterclose. It's succinctness daemon. General mileage can vary.

I think "succintness" is quite a secondary motivation; what generally
drives me to "collect" repetitively coded behavior into one class, function,
iterator, metaclass, template, macro, or other such "collecting" construct
that a language may make available to me, is the desire to remove duplication
of code -- both (primarily) duplication of meaningful code, and (secondarily) 
boilerplate code too.

I.e., it's fighting the "copy and paste" daemon, with all of its minuses.

Having to code empty special methods for common cases is an example
of boilerplate I'd much rather do without, in a somewhat different context
than that of "collecting" constructs (though such constructs may at times
be usable to alleviate the problem).  Consider the only way in which I
find classic classes preferable to new-style ones, now that I have some
substantial amount of experience using and teaching each kind...:

class Ic:
    "whatever contents, but no __init__"
ok = Ic()             # fine
notok = Ic(23)     # raises an exception, just like it should

__metaclass__ = type
class Nu:
    "whatever contents, but no __init__"
ok = Nu()             # fine
notok = Nu(23)     # "fine" -- *eep!!!* -- masks an error...!


To ensure runtime catching of what's typically an error, passing
parameters to the class that will be ignored, I have to do nothing
special in a classic class, but I do have to have some
    def __init__(self): pass
for a new-style class.  I can define a custom metaclass (a
subclass of 'type') or baseclass (a subclass of 'object') to
relegate this tiny wart (if wart it be) appropriately, of course:

class noinit(object):
    def __init__(self): pass

and then subclass noinit rather than subclassing object, or use
the (more complicated to code, but perhaps more transparent
in use) metaclass equivalent, e.g., something like:

class noinittype(type):
    def __new__(cls, classname, bases, classdict):
        if not bases and not classdict.has_key('__init__'):
            bases = noinit,
        return type.__new__(cls, classname, bases, classdict)

with a __metaclass__=noinittype in global scope.


Generally, I think that when the language offers ways to
reduce code duplication (including boilerplate), those ways
WILL eventually be used -- at least by some coders -- because
code duplication is such a blight (and many experienced coders
have been taught by bitter experience to perceive it as such).

That's part of why I'd much rather see macros *NOT* added
to Python: I feel that, if they are there, they WILL eventually
become widely used -- appropriately in some cases, sure, but
(I fear) quite obfuscatingly in many other cases.  Similar, even
though probably weaker, qualms can be raised about other
wide-use mechanisms (not quite as wide and powerful as
macros might be) that can reduce code duplication -- they
WILL be widely used.  The richer and potentially more
complicated the mechanism is, the more such wide use
can be seen as a rather mixed blessing.


Alex