Subject: Re: Lisp is *SLOW*
From: Erik Naggum <>
Date: 1997/08/08
Newsgroups: comp.lang.lisp
Message-ID: <>

* Jamie Zawinski
| If you have a recursive function that does a dynamic bind, or allocation,
| or whatever, around each call to itself, then I wouldn't consider that
| tail-recursive.  Sure, you've saved the call-stack, but that's not the
| whole story.

I agree that it's not the whole story, but I'm talking more about the
general ability to do tail-call merging than when specifically applied to
calling yourself.  my point was that other call-related expenses may be
worth saving.  e.g., on a SPARC, stack growth per call is large, and the
cost of save and restore involving register windows moved to and from stack
is very high.  other CPUs have other costs.  we do tail-call merging for
several good reasons and I believe all of them are related to reducing
costs, so if we can identify additional costs and ways to reduce them, that
would be a win.

| What reasons were you thinking of?  Perhaps there are also *other*
| reasons not to attempt to do tail-calls with emacs-lisp, but the dynamic
| binding showstopper was the point at which I stopped thinking about it...

I wanted to show that the way dynamic bindings and unwind-protects are
organized into a separate stack in Emacs Lisp (and probably not _entirely_
differently in other Lisps) was not an argument _against_ tail-call merging
in the presence of these forms.  you argue against tail-call merging based
on other factors in Emacs Lisp, and that's cool -- I didn't expect Emacs
Lisp to get tail-call merging just because it's possible, when it isn't
cost effective.

the question is only "how do you know how far to unwind", and if that is
something like a "mark" on a stack, like in Emacs Lisp, instead of constant
number of elements on the stack, like the C calling convention where the
caller must clean up the stack, I see opportunities for saving more costs.
not that I know any other Lisp intimately, but from what I have read
elsewhere, this does seem like a straight-forward way to do it, and would,
in other words, not remove the prospect of having efficient function calls
through the use of tail-call merging just because more powerful features
are also needed and used.

| Emacs-lisp isn't a good example of much of anything, really.

maybe not a _good_ example of anything, but a valid example of many things.
I'm aware that you don't like Emacs Lisp, and I have my own set of gripes,
but that doesn't mean everything that comes from Emacs Lisp is tainted.

404 Give me a URL I cannot refuse.