Page 1 of 1

Switch package

Posted: Mon Mar 21, 2011 4:26 am
by churib
Hi!

I am trying to write a macro, which dynamically binds the current package:

Code: Select all

(defmacro with-in-package (package-designator &body body)
  `(let ((*package* (find-package ,package-designator)))
     ,@body))
which expands like this:

Code: Select all

(macroexpand-1 '(with-in-package :sb-cltl2 (variable-information '*package*)))
(LET ((*PACKAGE* (FIND-PACKAGE :SB-CLTL2)))
  (VARIABLE-INFORMATION '*PACKAGE*))
but evaluating it gives me an error [SBCL]:

Code: Select all

(with-in-package :sb-cltl2 (variable-information '*package*))
->The function VARIABLE-INFORMATION is undefined.
but this works:

Code: Select all

(sb-cltl2:variable-information '*package*)
:SPECIAL
NIL
((TYPE . PACKAGE))
The macro IN-PACKAGE does nothing else than setting the value of *PACKAGE* (http://www.lispworks.com/documentation/ ... in_pkg.htm).

What do I miss?

Re: Switch package

Posted: Mon Mar 21, 2011 6:06 am
by pjstirling
COMMON-LISP:*PACKAGE* is used by the reader to pick the package to intern unknown symbols as they are read. What is happening is that the form (WITH-IN-PACKAGE :SB_CLTL2 (VARIABLE-INFORMATION '*PACKAGE*) is read, VARIABLE-INFORMATION is interned in whatever package you had to start (probably CL-USER) and then it attempts to execute it. Since the symbol VARIABLE-INFORMATION is not the one from SB-CLTL2, it isn't FBOUNDP, and so you get an error.

You need a reader macro to change the value of *PACKAGE* mid-form.

If you were only to use symbols from packages that are imported by both *PACKAGE* and whichever package you are trying to temporarily bind, then *PACKAGE* probably be whatever you set it to, it just wouldn't be doing what you want (unless you are also calling READ in the body).

Re: Switch package

Posted: Mon Mar 21, 2011 7:04 am
by churib
Wow - your answer is eye-opening for me! Thanks!