Search code examples
common-lispidentifier

Variations in invocation of defpackage and in-package


In Graham's book “ANSI Common Lisp” (1996) p. 137 the example illustrating the use of defpackage and in-package goes like

(defpackage "MY-APPLICATION"
  (:use "COMMON-LISP" "MY-UTILITIES")
  (:nicknames "APP")
  (:export "WIN" "LOSE" "DRAW"))

(in-package my-application)

The defpackage invocation uses of character strings to convey package names and list exported symbols. While this style can be seen in older codes the dominant usage today seems to be

(defpackage :my-application
  (:use :common-lisp :my-utilities)
  (:nicknames :app)
  (:export :win :lose :draw))

(in-package :my-application)

The regularity resulting from using the :my-application keyword both in the defpackage and in the in-package invocations is a minor but appreciable difference.

I speculate, the second forms reduces the size of the program in memory because the keywords are all interned in the keyword package while literal character strings stand for themselves and literal character strings with identical contents do not need to share their memory representations. (And if they did, strange results could follow from mutating one of these character strings!)

What are the actual differences between these two forms, and why is the latter preferred over the former?

Besides this, I occasionally see

;; Pay attention to the :export line
(defpackage :my-application
  (:use :common-lisp :my-utilities)
  (:nicknames :app)
  (:export #:win #:lose #:draw))

(in-package :my-application)

The # introduces a reader macro but I am not sure which effects it has on a keyword and not sure how it modifies the defpackage declaration.


Solution

  • tl;dr

    Use uninterned symbols, like #:my-package.

    String designators

    Common lisp has a notion of a string designator (see also designators).

    This means that operationally symbols in defpackage are equivalent to their names.

    Which designator to use?

    You have 4 options:

    1 Interned symbol

    E.g.,

    (defpackage my-package)
    

    Advantage

    Brevity

    Disadvantage

    Namespace pollution: the symbol my-package is now interned in the current *package*.

    2 Keyword

    E.g.,

    (defpackage :my-package)
    

    Advantage

    Moderate brevity (one extra character)

    Disadvantage

    Namespace pollution: the symbol :my-package is now interned in the standard package KEYWORD.

    3 String

    E.g.,

    (defpackage "MY-PACKAGE")
    

    Advantage

    No namespace pollution.

    Disadvantages

    • Ugly upcase
    • 2 extra characters

    4 Uninterned symbol

    E.g.,

    (defpackage #:my-package)
    

    Advantage

    No namespace pollution.

    Disadvantages

    2 extra characters

    The "ugly prefix" is actually a desirable feature because this is the only context where I use uninterned symbols, and emacs highlights them nicely if you add

    (font-lock-add-keywords
     'lisp-mode
     '(("\\(#:\\)\\(\\(\\s_\\|\\sw\\)*\\)"
        (1 font-lock-comment-delimiter-face)
        (2 font-lock-doc-face))))
    

    to your ~/.emacs.