Lisp HUG Maillist Archive

Using macro to define macros and functions in the current package?

I have been experimenting with macros, packages and symbols, and it
seems there may be something I do not quite understand.

Let's say I have a packages :util and :zip. :util is utilities
package, which has a macro-defining macro foo, which I call from
package :zip. I would expect that the calls interns the symbols to
package :zip but it seems it interns them into :util.

In the example below I would expect to see symbols ZIP::BAR and ZIP::Y
in the macroexpansion, not UTIL::BAR and UTIL::Y. Can somebody explain
why this is so? Is there a way to prevent this?

CL-USER 61 : 1 > (defpackage :util (:use :common-lisp))
#<The UTIL package, 0/16 internal, 0/16 external>

NAPLES 62 : 1 > (in-package :util)
#<The UTIL package, 0/16 internal, 0/16 external>

UTIL 63 : 1 > (defmacro foo ()
  `(defun bar (y)
      (format t "y=~A~%" y)))
FOO

UTIL 64 : 1 > (defpackage :zip (:use :common-lisp))
#<The ZIP package, 0/16 internal, 0/16 external>

UTIL 65 : 1 > (in-package :zip)
#<The ZIP package, 0/16 internal, 0/16 external>

ZIP 66 : 1 > (pprint (macroexpand-1 '(util::foo)))

(DEFUN UTIL::BAR (UTIL::Y) (FORMAT T "y=~A~%" UTIL::Y))

Best regards,

Mikko


Re: Using macro to define macros and functions in the current package?

On Thu, Apr 16, 2009 at 03:26:20PM +0300, Mikko Ahonen wrote:
> I have been experimenting with macros, packages and symbols, and it
> seems there may be something I do not quite understand.
> 
> Let's say I have a packages :util and :zip. :util is utilities
> package, which has a macro-defining macro foo, which I call from
> package :zip. I would expect that the calls interns the symbols to
> package :zip but it seems it interns them into :util.

Calling UTIL::FOO in your example doesn't actually intern any new
symbols.  The symbols are interned when they're read, which happens
only once, when you define the macro FOO, in package UTIL.  When you
invoke FOO, it macro-expands into (in this case) a constant list with
already-interned symbols in it.

> In the example below I would expect to see symbols ZIP::BAR and
> ZIP::Y in the macroexpansion, not UTIL::BAR and UTIL::Y. Can
> somebody explain why this is so? Is there a way to prevent this?
> 
> CL-USER 61 : 1 > (defpackage :util (:use :common-lisp))
> #<The UTIL package, 0/16 internal, 0/16 external>
> 
> NAPLES 62 : 1 > (in-package :util)
> #<The UTIL package, 0/16 internal, 0/16 external>
> 
> UTIL 63 : 1 > (defmacro foo ()
>   `(defun bar (y)
>       (format t "y=~A~%" y)))
> FOO

This is similar to

  (in-package :util)

  (defmacro foo ()
    (make-foo-definition))

  (defun make-foo-definition ()
    '(defun bar (y)
	(format t "y=~A~%" y)))

You wouldn't expect calling MAKE-FOO-DEFINITION to return symbols in
any package but UTIL, would you?  So macro-expanding FOO necessarily
returns a list with symbols in UTIL.

Hope that helps.

-- Larry


Re: Using macro to define macros and functions in the current package?

Both excellent answers, thank you. It seems so obvious now...

So to answer my own question, the basic idea how to define functions
in package of macro call is:

(defmacro foo ()
  `(defun ,(intern "BAR") ()))

Mikko

On Thu, Apr 16, 2009 at 4:38 PM, Chris Riesbeck
<c-riesbeck@northwestern.edu> wrote:
>
> Larry Clapp wrote:
>>
>> On Thu, Apr 16, 2009 at 03:26:20PM +0300, Mikko Ahonen wrote:
>> >
>>>
>>> In the example below I would expect to see symbols ZIP::BAR and
>>> ZIP::Y in the macroexpansion, not UTIL::BAR and UTIL::Y. Can
>>> somebody explain why this is so? Is there a way to prevent this?
>>>
>>> UTIL 63 : 1 > (defmacro foo ()
>>>  `(defun bar (y)
>>>      (format t "y=~A~%" y)))
>>> FOO
>>
>> This is similar to
>>
>>  (in-package :util)
>>
>>  (defmacro foo ()
>>    (make-foo-definition))
>>
>>  (defun make-foo-definition ()
>>    '(defun bar (y)
>>        (format t "y=~A~%" y)))
>>
>> You wouldn't expect calling MAKE-FOO-DEFINITION to return symbols in
>> any package but UTIL, would you?  So macro-expanding FOO necessarily
>> returns a list with symbols in UTIL.
>
> As for "Is there a way to prevent this?" consider
>
>  (DEFSTRUCT FOO A B)
>
> It constructs and INTERNs names like FOO-A, FOO-B and MAKE-FOO when the
> DEFSTRUCT call is expanded, so they go into the package in effect at the
> macro call.
>
> --
> Chris Riesbeck
>
> Home page: http://www.cs.northwestern.edu/~riesbeck/
> Calendar: http://calendar.yahoo.com/criesbeck
>
>


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