[Edu-sig] quantum instance
Dethe Elza
delza at livingcode.org
Wed Sep 14 06:19:22 CEST 2005
Arthur,
You may be happy to know that hard-core computer scientists cannot
agree on the benefits of abstractions such as decorators.
Paul Graham attributes power and elegance to the tersest languages[1]
[2], claiming that fewer lines of code means fewer bug, less time
writing the code, and less time maintaining the code.
Meanwhile Richard Gabriel notes[2] that code can share with poetry
the aspect of Compression, in which a few words can hold a great deal
of meaning, but he is careful to note that this can easily be taken
too far, resulting in incomprehensible gibberish (in poetry or in code).
Perhaps this comes down to the fact that both men are old hands at
Lisp, but while Graham literally wrote the book on Common Lisp[3],
Gabriel wrote "A Critique of Common Lisp."
Graham used a simplistic program to demonstrate succinctness, a straw
man I could argue against, but it demonstrates what I'm talking
about, using Python's standard foil: Perl. The goal is to create a
function which generates accumulators: Given a number n, it will
return a new function which takes another number i, and returns n
incremented by i, storing the accumulating result.
Graham's canonical example is in Common Lisp, and is indeed quite
succinct.
(defun foo (n)
(lambda (i) (incf n i)))
And in Perl you have
sub foo {
my ($n) = @_;
sub {$n += shift}
}
Which is succinct and perhaps readable to someone thoroughly familiar
with Perl, but does look like line noise to me.
Perhaps the most succinct you can get this in Python is the following:
def foo(n):
def bar(i, l=[n]):
l[0] += i
return l[0]
return bar
Although this is quite a bit longer than the Lisp version, it is
nearly as unreadable as the Perl code. In part this is because
Python distinguishes between expressions and statements, so we cannot
"return l[0] += i". Also, Python does not allow us to assign to
local integers, so we hack around this by putting the integer "n" in
a mutable container "l = [n]". And lambdas don't allow statements
(or is it expressions?) so that keeps it from getting succinct as well.
But of course, this is not the canonical Python. Canonical Python
would create a class:
class foo:
def __init__(self, n):
self.n = n
def __call__(self, i):
self.n += i
return self.n
As you can see, this is not much longer, and (in my eyes at least),
vastly more readable. No hacks with lists, it clearly shows that
we're accumulating the value. If I were to use this in any real
system, I would change "self.n" to "self.accumulator" or some such,
and make it even longer, because readability counts more than
succinctness, despite what Graham claims[5].
If you're still reading this far you may have noted that I haven't
actually talked about decorators at all. In my code, I have come to
places where there are aspects which cut across classes and methods
in a way that's not always intuitive or easy to capture in standard
object-oriented code. In Java and some other languages they are
implementing Aspect-Oriented Programming (AOP), where you create
"cutpoints" where code will be injected for different "aspects" which
are defined elsewhere. Generating this code is called "code weaving"
or "aspect weaving" and the result is not intended to be read or
modified by humans. Debugging this type of code must take the
patience of a saint, since all your line numbers and references would
have disappeared in the warp and weft.
With decorators I get an 80/20 solution to aspects which cover all of
the most common (and dare I say, important) uses of AOP, without
compile-time weaving, or losing line numbering or stack tracing or
any of my standard editing, reading, or debugging toolkit. For me,
this is a big win, and I'm happy to have decorators in my toolbox.
I'm also quite happy to have generators, list comprehensions,
properties, and descriptors, because these all fill needs for times I
have bumped up against a wall of complexity and my code has grown too
big, too multi-branched to fit comfortably in my head. Since I do a
lot of "hobby coding" in my limited spare time, on a lot of different
project, being able to fit the code in my head is essential. I need
to be able to come to a project I left off with months ago and
quickly grok what it does and why.
That said, I don't make daily use of decorators, descriptors,
properties, or even generators. Just as a carpenter's toolbox may
contain hammers and screwdrivers he uses everyday, and also more
specialized planes or chisels he uses more rarely (but still values
having the right tool for the job when he needs it), these are my
more specialized tools. I do use list comprehensions daily, they
have become one of my favored hammers, but I do try to take care to
use them in a way which enlightens the code rather than obfuscates
it, which they can certainly do.
And while Lisp hackers like Graham cannot understand why anyone
wouldn't want to use his all-powerful language, the Smalltalk
community is equally amused when the concepts they cut their teeth on
in the seventies are finally adopted by more mainstream languages
[6]. Power quote: "Reinventing Smalltalk, one decade at a time."
--Dethe
[1] http://www.paulgraham.com/icad.html (especially see "Appendix:
Power" at the end).
[2] http://www.dreamsongs.com/NewFiles/PatternsOfSoftware.pdf (Reuse
vs. Piecemeal Growth chapter)
[4] http://www.paulgraham.com/acl.html (ANSI Common Lisp)
[3] http://dreamsongs.com/NewFiles/clcrit.pdf (A Critique of Common
Lisp)
[5] http://www.paulgraham.com/power.html (Succinctness is Power, a
direct attack on Python)
[6] http://www.intertwingly.net/blog/2005/09/09/The-Case-for-Dynamic-
Languages (slides link)
"And you think you're so clever and classless and free"
— John Lennon on prototype-based programming
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2488 bytes
Desc: not available
Url : http://mail.python.org/pipermail/edu-sig/attachments/20050913/a4d8e99a/smime.bin
More information about the Edu-sig
mailing list