Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lisp recursive macro problems

I'm writing a recursive Lisp macro taking a number n and evaluating the body n times (an exercise from ANSI Lisp). I've tried two ways of doing this -- having the macro call itself in its expansion, and having the macro expand into a local recursive function. Neither works as I want it to.

Here's the first one -- it has a stack overflow, but when I look at its expansion using macroexpand-1 it seems fine to me.

(defmacro n-times (n &rest body)
  (let ((i (gensym)))
    `(let ((,i ,n))
     (if (zerop ,i) nil
         (progn
           ,@body
           (n-times (- ,i 1) ,@body))))))

Here's the second one -- it makes an error, "undefined function #xxxx called with arguments (z)" where #xxxx is the name of the gensym and z is 1 less than the number I call it with. I think there's a problem with the way I use gensyms and flet together, but I'm not sure how to do this correctly.

(defmacro n-times (n &rest body)
  (let ((g (gensym)))
    `(flet ((,g (x)
              (if (zerop x) nil
                  (progn
                    ,@body
                    (,g (- x 1))))))
       (,g ,n))))
like image 862
lightlike Avatar asked Feb 24 '26 12:02

lightlike


1 Answers

To answer your first question, you have a recursive macro expansion that never stops recursing. The presence of the if doesn't stop the recursive macro expansion, since macro expansion happens at compile-time and your if happens at run-time.

To answer your second question, you can't use flet to specify recursive functions, you have to use labels instead.

like image 155
Chris Jester-Young Avatar answered Feb 27 '26 02:02

Chris Jester-Young