Potting Soil: Count the Colons

Exported and Unexported Symbols

Like a lot of other languages, Common Lisp uses the colon (:) as a scope-resolution operator. FOO:BAR means the symbol named BAR in the package named FOO. But one can also have FOO::BAR (two colons) and :BAR. What's the difference?

A Lisp package is a collection of symbols. Some of those symbols are "exported," meaning they're meant to be used by functions in other packages. Exported symbols are like public methods in an object-oriented language. They're the public API that users of your package should follow. "Unexported" symbols are like private methods or private member variables, except that in Lisp they're not really private.

If (and only if) a symbol has been exported from a package, you can refer to it from another package with a single colon, e.g. PACKAGE:SYMBOL. Trying to use an unexported symbol this way results in an error.

You can always get at any symbol, regardless of whether or not it was exported, by using the double-colon (::) syntax, PACKAGE::SYMBOL.

The double-colon is a marker in the code that you're using an unexported symbol. If that symbol comes from someone else's library, then you probably shouldn't be doing that, because it's not part of the API.

DEFPACKAGE

You can modify the list of exported symbols in a package with EXPORT and UNEXPORT. But normally a package's exported symbols are given in the DEFPACKAGE macro:

(defpackage "STUFF"
    (:use "COMMON-LISP")
    (:export "FOO" "BAR"))

Now you can use STUFF:FOO and STUFF:BAR. (see below for an explanation of why they're strings inside the DEFPACKAGE)

This is a quick way to learn about the interface to a new Lisp library: find all the DEFPACKAGE expressions and look at what they export.

Keywords

As a special case, a colon before a symbol name with no package name, e.g. :FOO, specifies a symbol in the KEYWORD package. Keyword symbols always evaluate to themselves (they can't store a value). Every time you use a new keyword symbol, it is automatically added to and exported from the KEYWORD package. So :FOO is identical to KEYWORD:FOO. Don't try to write it ::FOO.

Packages and Nesting

Another note: unlike namespaces in some languages, Lisp packages cannot be nested. You cannot have a symbol FOO::BAR::BAZ.

Unexported Symbols

The special syntax sharp-colon (#:) creates an "uninterned symbol." For more information on that, and an explanation of why I used strings in the DEFPACKAGE above, see Potting Soil: Uninterned Symbols

by Stuart Sierra


This page is linked from:

Potting Soil