alias package names in Common Lisp
Asked Answered
B

3

15

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.

Byram answered 6/3, 2015 at 19:52 Comment(0)
M
11

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")

(edit) And, from anywhere, you can use (uiop:add-package-local-nickname :nickname :package).

When nicknames were global, PLNs are now local to your package and don't pollute the global namespace.

Marla answered 22/2, 2021 at 18:26 Comment(1)
You need ASDF 3.3.5 for PLN, here's a one-liner to get it: github.com/lisp-tips/lisp-tips/issues/40Marla
E
23

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")
Eat answered 6/3, 2015 at 20:58 Comment(2)
I ignored this answer a few days ago, because it seemed too complicated to me. My short answer to the original question would be: (rename-package :original-package-name :original-package-name '(alias)).Estrella
The short answer is however incorrect because it removes existing nicknames.Comnenus
M
11

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")

(edit) And, from anywhere, you can use (uiop:add-package-local-nickname :nickname :package).

When nicknames were global, PLNs are now local to your package and don't pollute the global namespace.

Marla answered 22/2, 2021 at 18:26 Comment(1)
You need ASDF 3.3.5 for PLN, here's a one-liner to get it: github.com/lisp-tips/lisp-tips/issues/40Marla
F
3

Not directly. I used http://www.cliki.net/cl-package-aliases in my CL days, but it's pretty outdated ATM. Though other solutions are listed here https://github.com/avodonosov/local-package-aliases

Firstrate answered 6/3, 2015 at 20:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.