Thus Spake Skip Montanaro On the now historical date of Sat, 10 Jan 2004
Sam> I read the benchmark and I think it doesn't measure python in
it's Sam> target area. That's like taking a world-class marathon
runner and Sam> wondering why he doesn't compete well in a
I feel flattered. *blush*
You know, I sadly spent quite a bit of time debating which simile to use
there. I wandered around the house wondering what to put there.
Some rejected ideas:
"It's like asking Kasparov why he didn't win the weight-lifting
"That's like asking a world-class marathon runner why he doesn't compete
well in a weight-lifting competition."
"That's like asking a world-class weightlifter why they didn't do well in
the figure skating competition." (I almost used this one because it
conjures images of a burly Russian weight-lifter floundering on ice
skates. Very Monty-Python-esque.)
I chose the one I did in case I needed to later state that "Both figure
skating and marathon running are aerobic sports, but that doesn't mean
that the skills involved are the same."
Now, I feel compelled to justify my statement.
Let's look closely at the benchmarks and try to figure out if there's a
good reason why we fell down where we did.
We did poorly at Math, and competitively at I/O.
I'm reminded of Antoine de Saint-Exupe'ry saying "A designer knows he has
achieved perfection not when there is nothing left to add, but when there
is nothing left to take away." While not part of the Zen of Python, this
seems to be an unstated principle of Python's design. It seems to focus
on the bare minimum of what's needed for elegant expression of algorithms,
and leave any extravagances to importable libraries.
Why, then, are integers and longs part of Python itself, and not part of a
library? Well, we need such constructs for counters, loops and indexes.
Both range and xrange are evidence of this. Were it not for this, I
daresay that we'd have at least argued the necessity of keeping these
things in the language itself.
Floats are a pragmatic convenience, because it's nice to be able to throw
around the odd floating point number when you need to. Trig functions are
housed in a separate library and notice that we didn't do too shabby there.
I/O is one of our strengths, because we understand that most programs are
not algorithmically bound, but rather I/O bound. I/O is a big
bottle-neck, so we should be damn good at it. The fastest assembly
program won't do much good if it's always waiting on the disk-drive.
Perhaps our simplicity is the reason we hear so many Lisp'ers vocally
complaining. While more pragmatic than Lisp, Python is definitely edging
into the "Lambda Calculus Zone" that Lisp'ers have historically been the
proud sole-occupants of. After all, until Python, when one wanted a
nearly theoretical programming experience, one either went to C/Assembly
(Turing Machine Metaphor) or Lisp (Lambda Calculus Metaphor.)
Python is being used in so many introductory programming courses for the
very reason that it so purely fits the way a programmer thinks, while
still managing to be pragmatic. It allows for a natural introduction to
some of the hardest concepts: Pointers/Reference, Namespaces, Objects and
Legibility. Each of these concepts is difficult to learn if you are first
indoctrinated into an environment without them. In my attempts to learn
C++, I initially felt like I was beating my head up against a wall trying
to learn what an object was and why one would use them. I have since
observed that people coming from a strongly functional programming
background have the same experience, while those with no functional
programming dogma in them find objects quite a natural concept. The same
thing is true of the other concepts I mentioned. If you have them, it's
easy to work without them. If you don't, you'll flounder trying to pick
them up. Think about how easy it is to pick out a C programmer from their
Python coding style.
The one important concept I didn't mention is message-passing. This is an
important, but much less used concept. It is the domain of Smalltalk and
Ruby. I've looked some at Ruby, and lurk their Usenet group. From what I
can tell, Ruby takes almost the same philosophy as Python, except where we
think namespaces are a honking great idea, they think message-passing is a
honking great idea. The nice thing about message-passing is that if you
have all the other concepts of OO down, message passing seems natural and
is not terribly difficult to "fake" when it's the only missing OO
primitive. This is why C++, while not a message-based OO language, is
used so often in GUI's, an inherently message-based domain. This is also
why we have such a nice, broad choice of GUI toolkits under Python despite
lacking a message primitive.
Well, I've blathered enough on this topic.
I hope, at least, that I've said something worthwhile.
Though, I doubt I've said anything that hasn't been said better before.
Caffeine, Boredom and Usenet are a dangerous mix.