

Q about Exercise 10.4 in "ANSI Common Lisp" - paul_reiners

I came up with the following solution for Exercise 4 in Chapter 10 of "ANSI Common Lisp" by Paul Graham:<p><pre><code>  (defmacro ntimes (n &#38;rest body)
    (let ((h (gensym)))
      `(let ((,h ,n))
         (if (&#62; ,h 0)
            ,@body)
         (if (zerop ,h)
             nil
             (ntimes (1- ,h) ,@body)))))
</code></pre>
Using GNU CLISP 2.44, this works fine.  However, when I use SBCL 1.0.6 via Cusp v0.8.174 and do the following call:<p><pre><code>  (ntimes 10
          (princ "."))
</code></pre>
I get the following error:<p>Control stack exhausted (no more space for function call frames).  This is probably due to heavily nested or infinitely recursive function calls, or a tail call that SBCL cannot or has not optimized away.<p>What exactly is going on here?  Is my solution correct and SBCL is wrong, or is my solution incorrect but it just happens to work on CLISP?
======
pg
You've written a recursive macro. That is usually a mistake. Here (unless you
mean the first argument always to be a constant) you're recursing based on
values that won't be available till runtime, yet the macro could be expanded
at compile-time.

You should just expand into a do.

~~~
paul_reiners
I guess I'm not understanding the problem then, because I thought we were not
supposed to expand into a do, since the problem states:

"Define ntimes (page 167) to expand into a (local) recursive function instead
of a do."

Isn't the problem asking you to write this _without_ expanding into a do, or
am I missing something here? What would be a correct solution to the problem?

~~~
pg
Oops, didn't read the problem. Yes, as other commenters say, you should expand
into a call to a recursive function, not an expression that gets expanded
recursively.

If you were writing this for real you'd expand into a do, so this problem is
somewhat artificially difficult.

~~~
icky
> Oops, didn't read the problem.

You _wrote_ the problem. ;)

------
paul_reiners
Sorry about the non-pretty printing. It was nicely formatted, when I entered
it (I swear). Is there something like a <code> tag I could use?

Also, not all of the error message printed. What's up with that?

