From: Marco Baringer
Subject: Re: Macro/package problem
Date: 
Message-ID: <m2654dcykl.fsf@bese.it>
·······@gmail.com (Manuel Simoni) writes:

> I'm trying to define an anaphoric macro APROG1, that does what its
> name says :), namely evaluating the first form in its body, binding
> the variable named IT to the result, evaluating the remaining forms in
> the body with this new binding, and finally returning IT.
>
> However, I'm having trouble when using the macro from a different
> package.
>
> This is what I'm doing:
>
> (defpackage #:a (:use #:cl) (:export #:aprog1))
> (in-package #:a)
> (defmacro aprog1 (&body body)
>   (if (null body)
>       `(values)
>       `(let ((it ,(first body)))
>          ,@(rest body)
>          it)))
>
> (defpackage #:b (:use #:cl #:a))
> (in-package #:b)
> (aprog1 (make-window) (set-window-title it "bla"))
>
> This doesn't work (UNBOUND-VARIABLE) and the macroexpansion shows why:
>
> (LET ((A::IT (MAKE-WINDOW))) (SET-WINDOW-TITLE IT "bla") A::IT)
>
> Why are the ITs from the backquoted code sections interned in a
> different package than the &body code?

they're not. the body code is read in the B package, so the symbols in
BODY are in the package B (except ones which have an explicit package
marker). The macro code is read in the A package, so IT is an internal
(since you didn't export it) symbol in the A package.

You have a couple options:

1) export A::IT:

(defpackage :a (:use :cl) (:export :aprog1 :it))

2) create the symbol at macro expansion time:

(defmacro aprog1 (&body body)
  ...
  `(let ((,(intern "IT") ,(first body)))
     ...))

of course this assumes that *package* will be expected package at
macro expansion time (which is still different than read time).

3) don't use anaphoric macros. (this is what i'd suggest)

(defmacro prog1-let (var value &body body)
  `(let ((,var ,value))
     ,@body
     ,var))

-- 
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
     -Leonard Cohen