I find myself changing packages a lot, so I decided to create a convenience symbol macro for myself to save some time:
(in-package :cl-user)
(defpackage :package
(:nicknames p)
(:export :c)
(:use :cl))
(in-package :package)
(defun change-package ()
(format t "package name > ")
(let ((package-name (read)))
(in-package package-name)))
(define-symbol-macro c (change-package))
I want to be able to type p:c
in the REPL from within any package and change to package to the target package. The problem is that the in-package macro captures package-name
and treats it as the name of the package.
I tried creating a macro of my own...
(defmacro ip (package-name)
`(in-package ,package-name))
(defun change-package ()
(format t "package name > ")
(let ((package-name (read)))
(ip package-name)))
... but of course that didn't work either, since the macro simply expands to the variable name anyway:
(setq package-name 'new-package)
(macroexpand '(ip package-name))
;; (EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE)
;; (SETQ *PACKAGE* (SB-INT:FIND-UNDELETED-PACKAGE-OR-LOSE "PACKAGE-NAME")))
T
Questions:
in-package
macro so I can dynamically change the package?,
+ in-package
option)There are multiple problems:
IN-PACKAGE
is a macro, it does not evaluate its arg.
you can't write a macro, because they are expanded by the compiler BEFORE runtime
So either:
Eval a new IN-PACKAGE
form with the desired package. Use EVAL
.
just set cl:*package*
to the desired package
Why is IN-PACKAGE a macro? -> it expands into an EVAL-WHEN
form, making sure that there is a compile time side-effect when compiling a FILE