Lisp HUG Maillist Archive

Curious?

I must be missing something... 

I defined a macro that defines a macro. 

(defmacro defwrapper (name args &body body)
  ;; defines a macro that encapsulates its &body arg into a lambda and
  ;; calls a do-it routine with the lambda function. The do-it routine
  ;; contains the bulk of the the wrapper code. And the macro
  ;; generated wrapped code contains only a function call to the doit
  ;; routine.
  (let ((g!fn-name (gensym))
        (g!fn      (gensym))
        (g!body    (gensym)))
    `(progn
       (defun ,g!fn-name (,@args ,g!fn)
         ,@(subst `(funcall ,g!fn) '&body body))
       (defmacro ,name ((,@args) &body ,g!body)
         `(,',g!fn-name ,,@args (lambda () ,@,g!body))))))

When I evaluate this macro, and then use the resulting new macro to define another symbol, it works just fine. 

(defwrapper with-wrapped-thingy (a b c)
  (let ((ans (startup-fn a)))
    (unwind-protect
        &body ;; <-- this is where a funcall will be placed
      (shutdown ans b c))))

;; and now try to use the new macro

(with-wrapped-thingy (x y z)
    (doit x y z))

==> expands to:  (#:G31850 X Y Z (LAMBDA () (DOIT X Y Z)))

where #:G31850 is the name of the companion do-it function defined by defwrapper for with-wrapped-thingy.

But if I take the macro expansion of the newly created macro, evaluate it, and then try to apply it to produce a new binding, I get an error that the &body argument in the lambda expression is unbound.

The macro expansion for "with-wrapped-thingy" is:

(PROGN
  (DEFUN #:G31872 (A B C #:G31873)
    (LET ((ANS (STARTUP-FN A))) (UNWIND-PROTECT (FUNCALL #:G31873) (SHUTDOWN ANS B C))))
  (DEFMACRO WITH-WRAPPED-THINGY ((A B C) &BODY #:G31874)
    `(#:G31872 ,A ,B ,C (LAMBDA () ,@#:G31874))))

When I evaluate this expansion, and then use WITH-WRAPPED-THINGY, then I get the error:

(with-wrapped-thingy (x y z)
    (doit x y z))

==> The variable #:G31874 is unbound.

Eh???


Dr. David McClain
dbm@refined-audiometrics.com



Re: Curious?

On Wed, Apr 4, 2012 at 3:04 PM, David McClain
<dbm@refined-audiometrics.com> wrote:
> (PROGN
>   (DEFUN #:G31872 (A B C #:G31873)
>     (LET ((ANS (STARTUP-FN A))) (UNWIND-PROTECT (FUNCALL #:G31873) (SHUTDOWN
> ANS B C))))
>   (DEFMACRO WITH-WRAPPED-THINGY ((A B C) &BODY #:G31874)
>     `(#:G31872 ,A ,B ,C (LAMBDA () ,@#:G31874))))
>
> When I evaluate this expansion, and then use WITH-WRAPPED-THINGY, then I get
> the error:
>
> (with-wrapped-thingy (x y z)
>     (doit x y z))
>
> ==> The variable #:G31874 is unbound.
>
> Eh???

When you say you're evaluating that expression, do you mean you're
actually evaluating that expression (e.g., by hitting C-x C-e in some
IDEs, copy/pasting into the REPL, etc.)?  The reader syntax
#:symbol-name produces new uninterned symbols with the given name, so
#:G31874 and #:G31874 are *different* symbols.  E.g., (running in
SLIME, so the REPL and warning messages might be formatted a little
differently)

CL-USER> (defun test (#:a)	#:a)
;Compiler warnings :
;   In TEST: Undeclared free variable #:A
;   In TEST: Unused lexical variable #:A
TEST
CL-USER> (test 1)

The first warning is about the #:a in the function body (it's free)
and the second is about the #:a in the lambda list (it's never used).
If you need to type things like this, you can use the #n# notation.
E.g.,

CL-USER> (defun test (#1=#:a) #1#)
TEST
CL-USER> (test 2)
2

Is this the issue you're running into?

//JT

-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/


Updated at: 2020-12-10 08:36 UTC