Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

alias package names in Common Lisp

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.

like image 693
Daniel Shapero Avatar asked Mar 06 '15 19:03

Daniel Shapero


2 Answers

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.

  • https://lispcookbook.github.io/cl-cookbook/packages.html#package-local-nicknames-pln
  • https://github.com/phoe/trivial-package-local-nicknames compatibility library (should not be needed anymore)
like image 152
Ehvince Avatar answered Oct 28 '22 23:10

Ehvince


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")
like image 30
Rainer Joswig Avatar answered Oct 28 '22 23:10

Rainer Joswig