Re: Stack overflow
* Guenther Schmidt wrote:
> (defun my-make-list (n)
> (cond
> ((< n 1) nil)
> (t (cons nil (my-make-list (- n 1))))))
This function isn't properly tail recursive. It might be that some
compilers are smart enough to convert it into a tail-recursive version
of itself, and then convert that to iteration. However I very much
doubt that scheme-the-language would specify that this should happen.
(The tail-recursive equivalent is something like
(defun my-make-list/tr (n)
(labels ((mml (m a)
(if (< m 1) a (mml (1- m) (cons nil a)))))
(mml n '())))
)
While it's true that scheme makes some guarantees about tail calls
that CL does not, in fact many CL compilers, including LW, do convert
tail calls, possibly at suitable optimisation settings. Given the
above tail-recursive variant, and using the default optimisation
settings, LW does in fact convert the tail calls to iteration.
So what you are seeing isn't anything to do with tail-call conversion.
Both the scheme version and the CL version are building some huge
stack, and then unwinding it. The difference is, in fact, that the
implementation of Scheme you are using has a larger stack limit than
LW's default limit. I'm not really familiar with the details of the
LW implementation, but many CLs use the stack support from the
underlying hardware, and this is often somewhat limited (especially
for interpreted code as I suspect yours was where you have dozens of
interpreter frames). Many scheme implementations simply heap-allocate
the stack, since they more-or-less need to do this anyway to support
call/cc. Using the hardware stack support makes things like
coexistance with other languages (`foreign' code) a whole lot easier,
and that's often a design goal for CL implementations.
From the tone of your messages, I'd guess that Scheme is a much more
suitable language for you. Or perhaps one of the pure functional
languages. Or maybe woodwork?
--tim