Didier Verna <did
...@lrde.epita.fr> writes:
> For instance, I've heard people claiming that CLOS *must* be slow, given
> all the things it does dynamically (like computing the list of
> applicable methods for each generic function call). But these people
> forget (or just don't know) about memoization.
I generally agree with your statement of pain about the way people suggest
slowness where it dosen't exist or exaggerate it heavily where it does.
Rather than comment on those remarks, which I think stand fine as you've
written them, let me point out where the personal point of pain is for me:
Dynamic inheritance is semantically different than static inheritance
(and, in my opinion, more correct). It doesn't implement the same
semantics. So, of course, it has different performance
characteristics.
There is a philosophical issue that's overlooked when one says things like
"C is faster at addition than Lisp" because C isn't doing Lisp addition
quickly nor is Lisp doing C's addition slowly. The two associate different
operations with the symbol +. I happen to like the definition of plus that
says when you give it a number, x, and 1, you get something bigger than x.
The feature of that, to me, is it's more like the math I do. C says the
operation is really to do what the machine does, and that I should use some
other secret operation if I want the math thing, or make sure all my numbers
are small, but that the most important thing is speed.
Likewise, CLOS does inheritance correctly. It can't be done truly correctly
with static analysis, because when you have an abstract class, you end
up dispatching only on the statically known methods for that type. When you
do oher calls to other methods, and they dispatch, and so on, it's not just
fast vs slow, it's what methods are actually gonig to get called. If calling
a method on a parent class means you are giving up the right to have child
class methods be called, then that's not just speed but correctness... Of
course, this choice point in the design space is just "defined" to be right,
and program errors are tolerated as "the programmer knew this was the semantics
and wrote the wrong program". But I don't think that's the only possible
analysis. By that analysis, we could rename + to be - and vice versa in CL,
and say "that's how we define the semantics and all program errors that result
from our choice of naming are due to the programmer".
The static/dynamic thing was not done as a way of saying, as a community,
"we're too lazy to do things up front where they belong". Rather, we as a
community have said "we want to first choose what we want to say, and when
the right time is to say it, and only after that is done will we see about
making that maximally efficient". That leads to different consequences,
which we have optimized well. If there are better optimizations possible for
those semantics, let's see an apples-to-apples comparison. But if we're
only going to talk apples-to-oranges, then the fight isn't fair from the
outset.