I'm using an external package in Common Lisp for a project; I want to be able to use the package but alias it to a shorter name, similar to how in Clojure I could do
(require '[unnecessarily-long-package-name :as ulpn])
In order to avoid naming conflicts, I'd rather not do this:
(defpackage #:my-package
(:use #:cl #:other-package))
(in-package :my-package)
(take-over-world "pinky" "brain")
where other-package
defines take-over-world
. I could just type the full qualified package name every time:
(defpackage #:my-package
(:use #:cl))
(in-package :my-package)
(other-package:take-over-world "pinky" "brain")
but in my case the package I'm importing has an unnecessarily long name. Is there a way I can use other-package
as
(op:take-over-world "pinky" "brain")
by aliasing it to op
? I wasn't able to find anything like this in the relevant chapter in Practical Common Lisp.
The way to do it now (since 2018 maybe?) is with Package-Local Nicknames (PLN), now available in most implementations.
(defpackage :mypackage
(:use :cl)
(:local-nicknames (:nickname :original-package-name)
(:alex :alexandria)
(:re :cl-ppcre)))
(in-package :mypackage)
;; You can use :nickname instead of :original-package-name
(nickname:some-function "a" "b")
When nicknames
were global, PLNs are now local to your package and don't pollute the global namespace.
In standard Common Lisp packages have global nicknames. You can give a package one or more nicknames in the DEFPACKAGE
definition:
(defpackage "LONGER-FOO"
(:use "CL")
(:nicknames "LF"))
For existing packages in plain Common Lisp use RENAME-PACKAGE:
rename-package package new-name &optional new-nicknames => package-object
Example:
CL-USER 1 > (defpackage "LONG-FOO" (:use "CL"))
#<The LONG-FOO package, 0/16 internal, 0/16 external>
CL-USER 2 > (let ((package (find-package "LONG-FOO")))
(rename-package package
(package-name package)
(adjoin "FOO"
(package-nicknames package)
:test #'string=)))
#<The LONG-FOO package, 0/16 internal, 0/16 external>
As a function:
Notice that we want to keep the existing nicknames by default.
(defun add-nickname (package nickname
&key (keep-existing-nicknames-p t))
(when (stringp package)
(setf package (find-package package)))
(check-type package package)
(check-type nickname string)
(rename-package package
(package-name package)
(if keep-existing-nicknames-p
(adjoin nickname (package-nicknames package)
:test #'string=)
(list nickname))))
Then we can call:
(add-nickname "LONG-FOO" "BAZ")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With