I've been complaining about stuff like this ever since PL/I in the 1960's!
At my first job, I had to go through the IBM source code & reimplment particularly
slow PL/I library functions.
What's the point of having an expressive language if the implementation
is so poor that you have to re-implement all the expressive parts anyway?
I (& most other people) have come to the same conclusion, which is why C
and C++ became so popular.
I've written about this problem in Common Lisp in a series of papers on my web
page. Basically, Common Lisp is designed to be incredibly difficult to optimize.
To your particular point, most of the Common Lisp 'sequence functions' should
really be 'inlined' (i.e., expanded inline as if they were macros). But the
ridiculously complicated 'keyword' arguments makes this pretty difficult.
Basically, if you really care about performance, you should learn to write
code while watching the machine code being emitted. You will likely be
pretty appalled by what gets done in most languages.
Also, almost any library function that is more than a few lines long is almost
certain to be suboptimal.
I just went through a Lisp exercise that involved 'hash consing', which uniquizes
every cons depending upon its CAR and CDR, recursively. If this is done correctly,
and there aren't any RPLACA or RPLACD operations, then EQUAL becomes EQ, and incredibly
fast.
Unfortunately, there is almost no way to implement this elegantly in Common Lisp,
so I had to do it in a Fortranish way with a CAR array and a CDR array. Common
Lisp hash tables don't accept user-defined 'equality-checking' predicates, which
makes Common Lisp builtin hash tables pretty worthless in my book.
At 05:59 PM 3/21/2013, Rupert Swarbrick wrote:
>PS For lisp gurus (or at least semi-gurus):
>
> If you look at the last patch in the series, you'll see a patch that
> changes something looking like
>
> (find-if (lambda (line-num) (<= start line-num end)) ses :key #'car)
>
> to the dolist form:
>
> (dolist (se ses nil) (when (<= start (car se) end) (return se)))
>
> This gives about a factor of 10 performance improvement on GCL, so
> was kind of needed. But, in between muttering imprecations about
> certain lisp implementations, I noticed that this also actually sped
> up the code on at least SBCL as well. Is there a reason that a
> compiler has to emit slower code for the find-if version?