ToC | DocOverview | CGDoc | RelNotes | FAQ | Index | PermutedIndex
| Allegro CL version 9.0 Unrevised from 8.2 to 9.0. 8.2 version

# Packages

This document contains the following sections:

1.0 Packages introduction
1.1 The current package on startup
2.0 Hierarchical Packages
2.1 Relative package names
2.2 Compatibility with ANSI Common Lisp
2.3 Package prefixes reserved by Allegro CL
2.4 New Common Lisp functions
2.5 The implementation of Hierarchical Packages
2.6 Testing the Hierarchical Packages Implementation
3.0 Packages in Allegro CL
4.0 Notes on specific packages
5.0 Package nicknames
6.0 Package locking and package definition locking
6.1 Package locking
6.2 Package definition locking
6.3 Implementation packages
6.4 Package locked errors
6.5 Locally circumventing package locked errors
6.6 The packages locked by default
6.7 Justification for package locking

## 1.0 Packages introduction

Common Lisp allows the use of packages to keep different parts of an application separate, permitting multiple use of symbol names and independent development of different parts of a large program. As delivered, Allegro CL comprises several packages, and users should be aware of which packages are available, which should be used by the user, and which should, in general, be avoided.

Starting in release 6.0, Allegro CL has implemented a hierarchical package naming scheme, allowing the specification of a hierarchy of packages, and the use of relative package specifiers, analogous to relative pathnames. While this facility is an extension to the ANSI spec, programs that do not use hierarchical naming are unaffected (except for the handling of rather unusual, erroneous code). Programs that use it, however, may have to be modified to be portable. See Section 2.0 Hierarchical Packages.

Lisp permits already-defined functions to be redefined dynamically. However, redefining system-defined functions (either from the Common Lisp standard in the common-lisp package or from the Allegro CL implementation, in packages such as excl, system, etc.) is almost always a bad idea. Allegro CL implements a package-locking system which protects symbols in reserved packages from new or changed function definitions. See the discussions under the heading Section 6.0 Package locking and package definition locking below.

## 1.1 The current package on startup

The initial package when Allegro CL is started in the :cl-user package when not starting in the IDE and the :cg-user package when starting the IDE. To change the initial package when using the IDE, see the section Note on the initial package in cgide.htm. When not using the IDE, see The package on startup in startup.htm.

## 2.0 Hierarchical Packages

The Common Lisp package system, designed and standardized some years ago, is not hierarchical. Since Common Lisp was standardized, other languages, including Java and Perl, have evolved namespaces which are hierarchical. This document describes a hierarchical package naming scheme for Common Lisp. We hope that CL implementations other than just Allegro CL will include this facility. All the source code used in Allegro CL to implement the facility is included below.

The goals of hierarchical packages in Common Lisp are:

- Reduce collisions with user-defined packages: it is a well-known problem that package names used by the Lisp implementation and those defined by users can easily conflict. The intent of hierarchical packages is to reduce such conflicts to a minimum.
- Improve modularity: the current organization of packages in various implementations has grown over the years and appears somewhat random. Organizing future packages into a hierarchy will help make the intention of the implementation more clear.
- Foster growth in Common Lisp programs, or modules, available to the CL community: the Perl and Java communities are able to contribute code to repositories, with minimal fear of collision, because of the hierarchical nature of the name spaces used by the contributed code. We want the Lisp community to benefit from shared modules in the same way.

In a nutshell, a dot (.) is used to separate levels in package names, and a leading dot signifies a relative package name. Absolute package names require no modifications to the underlying CL implementation. Relative package names require small and simple modifications, for which the source code is given below.

The choice of dot follows Java, Perl, another language with hierarchical packages, uses a colon (:) as a delimiter, but the colon is already reserved in Common Lisp.

Franz intends to extend the hierarchy below to currently existing packages. The Allegro CL test harness (see test-harness.htm) is in the util.test package.

## 2.1 Relative package names

Relative package names are needed for the same reason as relative pathnames, for brevity and to reduce the brittleness of absolute names.

A relative package name is one that begins with one or more dots. A single dot means the current package, two dots mean the parent of the current package, and so on.

Here are some examples, assuming that packages named mypack, `mypack.foo`, `mypack.foo.bar`, `mypack.foo.baz`, `mypack.bar`, `mypack.bar.baz`, `foo`, and `foo.bar`, have all been created:

relative name | current package | absolute name of referenced package
--- | --- | ---
`foo` | any | `foo`
`foo.bar` | any | `foo.bar`
`.foo` | `mypack` | `mypack.foo`
`.foo.bar` | `mypack` | `mypack.foo.bar`
`..foo` | `mypack.bar` | `mypack.foo`
`..foo.baz` | `mypack.bar` | `mypack.foo.baz`
`...foo` | `mypack.bar.baz` | `mypack.foo`
`.` | `mypack.bar.baz` | `mypack.bar.baz`
`..` | `mypack.bar.baz` | `mypack.bar`
`...` | `mypack.bar.baz` | `mypack`

Note 1: All packages in the hierarchy mentioned in the table above must exist in order for packages to be found via relative package names.

Note 2: WARNING ABOUT NICKNAMES! Unless you provide nicknames for your hierarchical packages (and we recommend against doing so because the number gets quite large), you can only use the names supplied. You cannot mix in nicknames or alternate names. `cl-user` (and `user`) are nicknames of the `common-lisp-user` package. Consider the following:

    (defpackage :cl-user.foo)

When the current package (the value of `*package*`) is `common-lisp-user`, you might expect `.foo` to refer to `cl-user.foo`, but it does not. It refers to the non-existent package `common-lisp-user.foo`. Note that the purpose of nicknames is to provide shorter names in place of the longer names designed to be fully descriptive. The hope is that hierarchical packages makes longer names unnecessary and thus makes nicknames unnecessary.

Note 3: multiple consecutive dots can only appear at the beginning. `foo.bar..baz` does not mean `foo.baz` -- it is invalid. (Of course, it is perfectly legal to name a package `foo.bar..baz` but find-package will not process such a name to find `foo.baz` in the package hierarchy.)

## 2.2 Compatibility with ANSI Common Lisp

The implementation of hierarchical packages modifies find-package and provides certain auxiliary functions, package-parent, package-children, and relative-package-name-to-package, as described in this section. (defpackage itself requires no modification.)

While the changes to find-package are small and described below, it is an important consideration for authors who would like their programs to run on a variety of implementations that using hierarchical packages will work in an implementation without the modifications discussed in this document. We show why not after describing the changes to find-package.

Absolute hierarchical package names require no changes in the underlying CL implementation.

### Changes to cl:find-package:

Using relative hierarchical package names requires a simple modification of find-package.

In ANSI CL, find-package, if passed a package object, returns it; if passed a string, find-package looks for a package with that string as its name or nickname, and returns the package if it finds one and returns `nil` if it does not; if passed a symbol, the symbol name (a string) is extracted and find-package proceeds as it does with a string.

For implementing hierarchical packages, the behavior when the argument is a package object (return it) does not change. But when the argument is a string starting with one or more dots not directly naming a package, find-package will, instead of returning `nil`, check whether the string can be resolved as naming a relative package, and if so, return the associated absolute package object. (If the argument is a symbol, the symbol name is extracted and find-package proceeds as it does with a string argument.)

In Allegro CL, find-package passes a string to the function excl::package-name-to-package, which returns a package object or `nil`. Without hierarchical packages, find-package returns `nil` if excl::package-name-to-package returns `nil`. With hierarchical packages, if excl::package-name-to-package returns `nil`, find-package calls excl::relative-package-name-to-package, which again returns a package object or `nil`. If `nil` is returned at this point, cl:find-package returns `nil`.

The complete source code for the modifications made to Allegro CL (except for the modifications to find-package) is given below and is in the public domain. It can be used by any CL vendor to augment their implementation to behave as this document suggests. find-package should be modified according to the description just above -- trying to resolve a name as relative if the name does not itself name a package.

Note that you should not use leading dots in package names when using hierarchical packages.

### Using hierarchical packages without modifying cl:find-package:

Even without the modifications to cl:find-package, authors need not avoid using relative package names, but the ability to reuse relative package names is restricted. The following example illustrates this:

> Consider a module foo which is composed of the my.foo.bar and my.foo.baz packages. In the code for each of these packages there are relative package references, ..bar and ..baz.

> Implementations that have the new cl:find-package would have on their `*features*` list the symbol `:relative-package-names`. Then, in the foo module, there would be definitions of the my.foo.bar and my.foo.baz packages like so:

>     (defpackage :my.foo.bar
>       #-relative-package-names (:nicknames #:..bar)
>       ...)

>     (defpackage :my.foo.baz
>       #-relative-package-names (:nicknames #:..baz)
>       ...)

> Then, in a `#-relative-package-names` implementation, the symbol `my.foo.bar:blam` would be visible from my.foo.baz as `..bar:blam`, just as it would from a `#+relative-package-names` implementation.

So, even without the implementation of the augmented find-package, one can still write CL code that will work in both types of implementations, but ..bar and ..baz are now used, so you cannot also have otherpack.foo.bar and otherpack.foo.baz and use ..bar and ..baz as relative names. (The point of hierarchical packages, of course, is to allow reusing relative package names.)

## 2.3 Package prefixes reserved by Allegro CL

Starting in Allegro CL 6.0, Franz Inc. typically puts newly created packages under the following top-level names:

- net -- network related modules
  - uri -- URI/URL/URN parser (see uri.htm)
  - aserve -- web server (see aserve/aserve.html)
  - rpc -- Lisp-to-Lisp remote procedure call (see rpc.htm)
- xml -- used for generated namespaces
- javatools
  - jlinker -- Java interface components (see jlinker.htm)
  - jil -- Java-in-Lisp bytecode compiler (see jil.htm)
- cg -- common graphics
- ide -- cg-based graphical development environment
- corba
- ffi -- foreign function related modules
- util -- utility modules

The use of these top-level names as packages in applications might run into problems with Allegro CL 6.0 and future versions. Note that all current package names (such as excl, system etc.) will also be used.

## 2.4 New Common Lisp functions

To facilitate using hierarchical packages, we introduce several new functions, other than the changed find-package: excl::relative-package-name-to-package, package-parent and package-children. The source code for these functions is also given below.

These functions are documented below with their implementation.

## 2.5 The implementation of Hierarchical Packages

    ;; The following source code is in the public domain.
    ;; Provided "as is" with no warranty of any kind.
    ;; Use at your own risk.

    (pushnew :relative-package-names *features*)

    (defun relative-package-name-to-package (name)
      ;; Given a package name, a string, do a relative package name lookup.
      ;;
      ;; It is intended that this function will be called from find-package.
      ;; In Allegro, find-package calls package-name-to-package, and the latter
      ;; function calls this function when it does not find the package.
      ;;
      ;; Because this function is called via the reader, we want it to be as
      ;; fast as possible.
      (declare (optimize speed))
      (flet ((relative-to (package name)
    	   (if* (string= "" name)
    	      then package
    	      else (package-name-to-package
    		    (concatenate 'simple-string
    		      (package-name package) "." name))))
    	 (find-non-dot (name)
    	   (do* ((len (length name))
    		 (i 0 (1+ i)))
    	       ((= i len) nil)
    	     (declare (fixnum len i))
    	     (when (char/= #\. (schar name i)) (return i)))))
        (when (char= #\. (schar (simple-string name) 0))
          (let* ((last-dot-position (or (find-non-dot name) (length name)))
    	     (n-dots last-dot-position)
    	     (name (subseq name last-dot-position)))
    	(cond ((= 1 n-dots)
    	       ;; relative to current package
    	       (relative-to *package* name))
    	      (t
    	       ;; relative to our (- n-dots 1)'th parent
    	       (let ((p *package*)
    		     tmp)
    		 (dotimes (i (1- n-dots))
    		   (when (not (setq tmp (package-parent p)))
    		     (error "The parent of ~a does not exist." p))
    		   (setq p tmp))
    		 (relative-to p name))))))))

    (defun package-parent (package-specifier)
      ;; Given package-specifier, a package, symbol or string, return the
      ;; parent package.  If there is not a parent, signal an error.
      ;;
      ;; Because this function is called via the reader, we want it to be as
      ;; fast as possible.
      (declare (optimize speed))
      (flet ((find-last-dot (name)
    	   (do* ((len (1- (length name)))
    		 (i len (1- i)))
    	       ((= i -1) nil)
    	     (declare (fixnum len i))
    	     (when (char= #\. (schar name i)) (return i)))))
        (let* ((child (cond ((packagep package-specifier)
    			 (package-name package-specifier))
    			((symbolp package-specifier)
    			 (symbol-name package-specifier))
    			((stringp package-specifier) package-specifier)
    			(t (error "Illegal package specifier: ~s."
    				  package-specifier))))
    	   (dot-position (find-last-dot child)))
          (cond (dot-position
    	     (let ((parent (subseq child 0 dot-position)))
    	       (or (package-name-to-package parent)
    		   (error "The parent of ~a does not exist." child))))
    	    (t (error "There is no parent of ~a." child))))))

    (defun package-children (package-specifier &key (recurse t))
      ;; Given package-specifier, a package, symbol or string, return all the
      ;; packages which are in the hierarchy "under" the given package.  If
      ;; :recurse is nil, then only return the immediate children of the
      ;; package.
      ;;
      ;; While this function is not called via the reader, we do want it to be
      ;; fast.
      (declare (optimize speed))
      (let ((res ())
    	(parent (cond ((packagep package-specifier)
    		       (package-name package-specifier))
    		      ((symbolp package-specifier)
    		       (symbol-name package-specifier))
    		      ((stringp package-specifier) package-specifier)
    		      (t (error "Illegal package specifier: ~s."
    				package-specifier)))))
        (labels
    	((string-prefix-p (prefix string)
    	   ;; Return length of `prefix' if `string' starts with `prefix'.
    	   ;; We don't use `search' because it does much more than we need
    	   ;; and this version is about 10x faster than calling `search'.
    	   (let ((prefix-len (length prefix))
    		 (seq-len (length string)))
    	     (declare (fixnum prefix-len seq-len))
    	     (when (>= prefix-len seq-len)
    	       (return-from string-prefix-p nil))
    	     (do* ((i 0 (1+ i)))
    		 ((= i prefix-len) prefix-len)
    	       (declare (fixnum i))
    	       (when (not (char= (schar prefix i) (schar string i)))
    		 (return nil)))))
    	 (test-package (package-name package)
    	   (let ((prefix
    		  (string-prefix-p (concatenate 'simple-string parent ".")
    				   package-name)))
    	     (cond (recurse (when prefix (pushnew package res)))
    		   (t (when (and prefix
    				 (not (find #\. package-name :start prefix)))
    			(pushnew package res)))))))

          ;; In Allegro, list-all-packages calls `sort', so use an internal
          ;; method to get the package names.
          #+allegro
          (maphash #'test-package *package-names*)
          #-allegro
          (dolist (package (list-all-packages))
    	(funcall #'test-package (package-name package) package))

          res)))

## 2.6 Testing the Hierarchical Packages Implementation

The following test code can be used to check a hierarchical package implementation. You must use the Allegro CL test harness, documented in the test-harness.htm. The test harness is loaded by the `(require :tester)` form.

    ;; The following source code is in the public domain.
    ;; Provided "as is" with no warranty of any kind.
    ;; Use at your own risk.

    (eval-when (compile eval load)
      (require :tester))

    (defpackage :package-tests
      (:use #:common-lisp #:excl #:util.test)
      (:import-from #:excl #:package-children)
      (:import-from #:excl #:package-parent))

    (in-package :package-tests)

    (defpackage :package-tests.a)
    (defpackage :package-tests.a.b)
    (defpackage :package-tests.a.b.c)
    (defpackage :package-tests.a.b.c.d)
    (defpackage :package-tests.a.b.c.d.e)
    (defpackage :package-tests.a.b.c.d.f)
    (defpackage :package-tests.a.b.c.e)
    (defpackage :package-tests.a.b.c.f)
    (defpackage :package-tests.a.b.d)
    (defpackage :package-tests.a.b.e)
    (defpackage :package-tests.a.c)
    (defpackage :package-tests.a.d)
    (defpackage :package-tests.b)
    (defpackage :package-tests.c)
    (defpackage :package-tests.d)

    (defpackage :package-tests-foo.bar.baz)
    (defpackage :package-tests-foo.bar.baz.wham)

    (defun do-package-tests ()
      (test t
    	(progn #+relative-package-names t
    	       #-relative-package-names nil)
    	:test #'eq)

    ;;;; test package-children
      (test '("package-tests.a" "package-tests.b"
    	  "package-tests.c" "package-tests.d")
    	(sort (mapcar #'package-name
    		      (package-children :package-tests :recurse nil))
    	      #'string<)
    	:test #'equal)
      (test '("package-tests.a" "package-tests.a.b" "package-tests.a.b.c"
    	  "package-tests.a.b.c.d" "package-tests.a.b.c.d.e"
    	  "package-tests.a.b.c.d.f" "package-tests.a.b.c.e"
    	  "package-tests.a.b.c.f" "package-tests.a.b.d" "package-tests.a.b.e"
    	  "package-tests.a.c" "package-tests.a.d" "package-tests.b"
    	  "package-tests.c" "package-tests.d")
    	(sort (mapcar #'package-name (package-children :package-tests))
    	      #'string<)
    	:test #'equal)
      (test '("package-tests.a.b.c.d" "package-tests.a.b.c.d.e"
    	  "package-tests.a.b.c.d.f" "package-tests.a.b.c.e"
    	  "package-tests.a.b.c.f")
    	(sort (mapcar #'package-name (package-children :package-tests.a.b.c))
    	      #'string<)
    	:test #'equal)
      (test '("package-tests.a.b.c.d" "package-tests.a.b.c.e"
    	  "package-tests.a.b.c.f")
    	(sort (mapcar #'package-name
    		      (package-children :package-tests.a.b.c :recurse nil))
    	      #'string<)
    	:test #'equal)
      (test '("package-tests.a.b.c.d.e" "package-tests.a.b.c.d.f")
    	(sort (mapcar #'package-name (package-children :package-tests.a.b.c.d))
    	      #'string<)
    	:test #'equal)
      (test '("package-tests.a.b.c.d.e" "package-tests.a.b.c.d.f")
    	(sort (mapcar #'package-name
    		      (package-children :package-tests.a.b.c.d :recurse nil))
    	      #'string<)
    	:test #'equal)
      (test '()
    	(package-children :package-tests.b)
    	:test #'equal)
      (test '()
    	(package-children :package-tests.c)
    	:test #'equal)
      (test '()
    	(package-children :package-tests.d)
    	:test #'equal)

    ;;;; test package-parent
      (test (find-package :package-tests)
    	(package-parent :package-tests.a))
      (test (find-package :package-tests.a)
    	(package-parent :package-tests.a.b))
      (test (find-package :package-tests.a.b)
    	(package-parent :package-tests.a.b.c))
      (test (find-package :package-tests.a.b.c)
    	(package-parent :package-tests.a.b.c.d))
      (test (find-package :package-tests.a.b.c.d)
    	(package-parent :package-tests.a.b.c.d.e))
      (test (find-package :package-tests.a.b.c.d)
    	(package-parent :package-tests.a.b.c.d.f))
      (test (find-package :package-tests.a.b.c)
    	(package-parent :package-tests.a.b.c.e))
      (test (find-package :package-tests.a.b.c)
    	(package-parent :package-tests.a.b.c.f))
      (test (find-package :package-tests.a.b)
    	(package-parent :package-tests.a.b.d))
      (test (find-package :package-tests.a.b)
    	(package-parent :package-tests.a.b.e))
      (test (find-package :package-tests.a)
    	(package-parent :package-tests.a.c))
      (test (find-package :package-tests.a)
    	(package-parent :package-tests.a.d))
      (test (find-package :package-tests)
    	(package-parent :package-tests.b))
      (test (find-package :package-tests)
    	(package-parent :package-tests.c))
      (test (find-package :package-tests)
    	(package-parent :package-tests.d))

      (test-error (package-parent :package-tests))
      (test-error (package-parent :package-tests-foo.bar.baz))
      (test-error (package-parent :package-tests-foo.bar))
      (test-error (package-parent :package-tests-foo))

    ;;;; test find-package
      (dolist
          (item
    	  '((:package-tests.a         :package-tests.a ".")
    	    (:package-tests           :package-tests.a "..")
    	    (:package-tests.b         :package-tests.a "..b")
    	    (:package-tests.c         :package-tests.a "..c")
    	    (:package-tests.d         :package-tests.a "..d")
    	    (:package-tests.a.b       :package-tests.b "..a.b")
    	    (:package-tests           :package-tests.a.b "...")
    	    (:package-tests.b         :package-tests.a.b "...b")
    	    (:package-tests.a.b.c.d.f :package-tests.a.b.c.d "...c.d.f")
    	    (:package-tests           :package-tests.a.b.c.d ".....")
    	    (:package-tests.b         :package-tests.a.b.c.d ".....b")
    	    (:package-tests.a.b.c.d   :package-tests.a.b.c.d ".")
    	    (:package-tests.a.b.c     :package-tests.a.b.c ".")
    	    (:package-tests.a.b       :package-tests.a.b ".")))
        (test (symbol-name (first item))
    	  (let* ((*package* (find-package (second item)))
    		 (p (find-package (third item))))
    	    (cond (p (package-name p))
    		  (t (error "could not find package ~s." (third item)))))))

      (test-error (find-package ".."))
      (test-error (find-package "..."))
      (test-error (find-package "...."))
      (test-error (find-package "....foo"))
      (let ((*package* (find-package :package-tests.b)))
        (test-error (find-package "..."))))

    (let ((*test-errors* 0)
          (*test-successes* 0)
          (*test-unexpected-failures* 0))
      (format t "Beginning package tests...~%")
      (do-package-tests)
      (format t "Completed package tests.~%")
      (format t "** Successes: ~s~%" *test-successes*)
      (format t "** Errors: ~s~%" *test-errors*)
      (format t "** Unexpected failures: ~s~%" *test-unexpected-failures*))

## 3.0 Packages in Allegro CL

In addition to the hierarchical packages named in Section 2.3 Package prefixes reserved by Allegro CL, the following packages used by Allegro CL are of direct importance to the user. Note that all nicknames are not listed in every case. Use package-nicknames applied to a package to see the complete list. The first nickname listed in each case is the principal nickname.

Some of these packages may not exist in a standard Allegro CL image until a fasl file containing the functionality associated with the package is loaded. In many cases, the loading is automatic when the package is referenced. Thus

    (find-package :flavors)

causes flavors.fasl to be loaded from the bundle. The cltl-1 module is not atoloaded.

Name | Some nicknames | Brief Description | Locked? | Notes
`acl-socket` |  | Socket interface functionality. See socket.htm. | No | Autoloaded
`aclwin` | aclwin302 | Functionality from Allegro CL 3.0.2 kept in 6.x for backward compatibility. | Yes | Exists in Windows and Unix. In Unix, do (require :aclwin) In Unix, symbols having to do with graphics have no function definition. Functionality that is Windows-specific generates an error when called in Unix.
`clos` |  | the MOP extension to CLOS (CLOS functionality is in common-lisp). | Yes | Always present in an image.
`cltl1` |  | Some symbols removed some functionality redefined from the Common Lisp standard by X3J13. | No | Functionality named by symbols in this package is out of date and use should be avoided. Not autoloaded.
`cg` | common-graphics | Common Graphics windows functionality. | Yes | Windows only. Always present in an image with the IDE.
`common-graphics-user` | cg-user | User environment in the IDE | No | Windows only. Uses aclwin, excl, cg, cl, ide. Always present in an image with the IDE.
`common-lisp` | cl | Standard CL symbols. | Yes | Always present in an image.
`common-lisp-user` | cl-user user | User environment. | No | Uses cl and excl. Always present in an image.
`compiler` | comp | Symbols naming functionality associated with the compiler. See compiling.htm. | Yes | Autoloaded.
`cross-reference` | xref | Symbols naming functionality associated with the cross referencer. See cross-reference.htm. | Yes | Autoloaded.
`dde` |  | Symbols naming functionality associated with the DDE interface on Windows. See dde.htm | No | Autoloaded.
`defsystem` |  | Symbols naming functionality associated with defsystem. See defsystem.htm | Yes | Autoloaded.
`debugger` | db | Symbols naming functionality associated with the debugger. See debugging.htm. | Yes | Autoloaded.
`excl` | excl | General extensions to Common Lisp | Yes | Always present in an image.
`foreign-functions` | ff | Symbols naming functionality associated with the foreign functions facility. See foreign-functions.htm. | Yes | Autoloaded.
`garbage` |  | Package for compiler labels and some CLOS names. | No | Always present in an image.
`ide` |  | Integrated Development Environment functionality. | Yes | Windows only. Always present in an image with the IDE.
`inspect` |  | Symbols naming functionality associated with the inspector. See inspector.htm. | Yes | Autoloaded.
`keyword` |  | Standard CL package. | No | Always present in an image.
`multiprocessing` |  | Symbols naming functionality associated with multiprocessing. See multiprocessing.htm. | Yes | Autoloaded.
`profiler` | prof | Symbols naming functionality associated with the runtime analyzer. See runtime-analyzer.htm. | Yes | Autoloaded.
`system` | sys, si | System functionality and internals. | Yes | Always present in an image.
`top-level` | tpl | Symbols naming functionality associated with the top level. See top-level.htm. | Yes | Always present in an image.

## 4.0 Notes on specific packages

When you start up Allegro CL on UNIX or without the Integrated Development Environment on Windows, you are in the `common-lisp-user` package. At the start, there are no symbols in the `common-lisp-user` package, but the `common-lisp` and `excl` packages are used, so external symbols from those packages are available to the `user` package. When you start the Integrated Development Environment (Windows only) you are in the `common-graphics-user` package.

The `common-lisp` package contains only those symbols specified in the ANSI CL specification. Some of the capabilities of standard Common Lisp functions have been extended, but they can all be used in the way specified in ANSI CL. The extensions are not portable, of course. See implementation.htm for more information on extensions to standard Common Lisp functionality.

With that caveat, if you use the common-lisp package only, you will have portable code that can with greatest ease be ported to Common Lisp systems other than Allegro CL.

A number of symbols were removed from the Common Lisp standard by the X3J13 committee. We have maintained many of these symbols in the `cltl1` package, for the purpose of providing backward compatibility.

The `excl` and `system` packages contain many of the extensions in Allegro CL. Two packages in earlier versions on UNIX (4.3.x and earlier), `franz` and `stream`, have been merged with `excl` starting in version 5.0. Both `stream` and `franz` are nicknames of `excl`. `excl` is also the principal nickname of the `excl` package to ensure that name is used when `*print-nickname*` is true.

The `top-level` package contains symbols used by the top level. Note that some of these symbols have the same names as symbols in the `common-lisp` package (for example, `*print-level*` and `*print-length*`). Therefore, we recommend that a package using the `common-lisp` package not use (in the sense of use-package) the `top-level` package.

## 5.0 Package nicknames

Packages can have (usually shorter) nicknames, which can be used in place of the full names. Symbols unavailable in the current package are printed (during, e.g., tracing) with package qualifiers. Allegro CL allows you to specify whether you want the (non-nickname) package name as the qualifier or the principal nickname as the qualifier. The following variable `*print-nickname*` controls whether the printer uses the full name or the principal nickname of a package (if true, the principal nickname is used, if `nil`, the package name is used). Note that certain utilities (e.g. apropos and the debugger) bind this variable to true and so always use the nickname.

The principal nickname of some of the packages of interest to users are listed next (`nil` means no defined nicknames).

Table 2: Package Nicknames
Package name | Principal Nickname (`nil` means none) | Other Nickname (some nicknames may not be listed)
`common-lisp` | `cl` | `lisp`
`clos` | `nil` |
`excl` | `nil` |
`system` | `sys` | `si`
`common-lisp-user` | `cl-user` | `user`
`debugger` | `debug` | `db`
`inspect` | `nil` |
`compiler` | `comp` |
`flavors` | `fla` |
`foreign-functions` | `ff` |
`multiprocessing` | `mp` |
`top-level` | `tpl` |
`defsystem` | `defsys` | `ds`
`cross-reference` | `xref` |

Package nicknames can be found with the Common Lisp function package-nicknames, which returns a list of the nicknames of its argument, with the principal one first. Sometimes, you may wish to use a nickname of an Allegro CL package as the name of your own package. (E.g. some users would like to have their own package named `db`, perhaps for database functionality, but `db` is a nickname of the `debugger` package.) You can change the nicknames of a package with rename-package. You must do it in a without-package-locks form, however, because of package locking described just below.

## 6.0 Package locking and package definition locking

Packages have two kinds of locks as an extension in Allegro CL. The package-lock protects a package from changes in its structure (its use list, its exported symbols, etc.). The package-definition-lock protects the symbols in the package from new or changed uses as the name of a function, macro, structure, or type.

Tracing and advice are not affected by either type of package locking.

## 6.1 Package locking

When the function package-lock returns true when applied to a package, we say the package is package-locked. When a package is package-locked, the system will signal an error of type package-locked-error when code is executed that tries to:

- import a symbol into the package (with import and shadowing-import)
- export a symbol from the package (with export).
- unexport a symbol (with unexport)
- change the name of the package (with rename-package).
- change the packages used by the package (with use-package and unuse-package).
- unintern a symbol in the package (with unintern)
- shadow a symbol (with shadow or shadowing-import).

The list is exhaustive. Note that intern and delete-package cannot signal a package-locked-error. The function package-lock applied to a package object (but not a symbol or string naming a package) returns true if the package is locked and returns `nil` if it is not locked. Setf can be used with package-lock to lock or unlock a package.

## 6.2 Package definition locking

A package is package-definition-locked if the function package-definition-lock (whose argument must be a package object, not a package name) returns true when applied to the package. When a package is package-definition-locked, the system will signal an error when code is executed that attempts any of the following actions on a symbol homed in the package:

- defining it as a function (e.g. with defun or setf of fdefinition)
- defining it as a macro (e.g. with defmacro)
- defining it as a type specifier (with defstruct, defclass, deftype)
- defining it as a structure (with defstruct)
- defining it as a symbol macro
- defining it as a compiler macro
- if the symbol is fboundp, lexically binding it with flet, labels, or macrolet

Function names that are lists are also protected if the important symbol (usually the cadr, e.g. border in `(setf border)`) in the list is in the definition-locked package. We repeat here the definition of package-definition-lock because it describes how the lock can be circumvented.

> > package-definition-lock

> > Arguments: package

> > Returns `t` or `nil` as package is or is not definition-locked. package must be a package object (it cannot be a symbol or a string). setf may be used with this function to definition-lock or unlock a package.

> > Even if a package is package-definition-locked, no error will be signaled when

> > > 1. the value of `*enable-package-locked-errors*` is `nil`;
> > > 2. the violation is dynamically inside the body of a call to the macro without-package-locks;
> > > 3. the list returned by applying package-implementation-packages to the value of `*package*` contains the home package of the symbol being operated on. Implementation packages are defined just below. Note that unless you have specified a list of implementation packages for a package that does not include the package itself (which would be unusual), no error will be signaled when `*package*` is the home package of the symbol being operated on. Also, no error is signaled if the value of `*package*` is the home package of the symbol being operated on regardless of the contents of package-implementation-packages.

> > If a violation is encountered while compiling a file, a warning is signaled rather than an error. If the resulting fasl file is loaded, an error will then be signaled.

## 6.3 Implementation packages

Allegro CL allows a package to have a list of associated packages (called implementation packages). No warning or error will be signaled for a definition or redefinition in one package when the value of `*package*` is an implementation package of that package. Both defpackage and make-package have been extended to accept an implementation-packages keyword argument and the setfable function package-implementation-packages accesses that list of packages.

The value of the implementation-packages argument to make-package should be a list of strings naming packages. The defpackage form should contain a subform which is a list whose first element is `:implementation-packages` and whose remaining elements are strings naming the desired packages (as shown in the example below). When unspecified, the list of implementation packages defaults to a list containing the string naming the package being defined. The implementation-packages argument is not standard Common Lisp. You may wish to conditionalize it in portable code, as shown next.

    (defpackage :mypack
        #+allegro (:implementation-packages "MYPACK"
                                            "MYPACK-2")
                    ; other options as desired
       )

The `:implementation-packages` option will only be read by Allegro CL. Note that since we specified a value, we had to include "MYPACK" as well as "MYPACK-2" in order to allow symbols whose home package is `mypack` to be redefined without warning or error while the value of `*package*` is the `mypack` package.

Note that implementation packages protects against warnings and errors for package definition locks only. Package locks (the distinction is described above) are not affected.

Here is an example. Suppose we define two packages: foo and bar. "BAR" is on the `:implementation-packages` list for foo, but "FOO" is not on the `:implementation-packages` list for `bar`. Both packages are definition-locked.

    (defpackage :foo (:implementation-packages "FOO" "BAR"))
    (defpackage :bar)
    (setf (package-definition-lock (find-package :foo)) t)
    (setf (package-definition-lock (find-package :bar)) t)

Consider the following two files. The first starts with `(in-package :bar)` and defines a function on foo::mysym. The second starts with `(in-package :foo)` and defines a function on bar::my-other-sym. Compiling or loading the first file signals no warning or error, since the bar package is an implementation package for the foo package. The second signals a warning on compilation and an error on loading because the `foo` package is not an implementation package for the `bar` package.

    ;; File # 1
    ;; Compiling or loading this file will not signal a warning
    ;; (for compilation)

    ;; or an error (for loading) even if the FOO package is
    ;; definition locked,
    ;; because the BAR package is an implementation package of
    ;; the FOO package.
    (in-package :bar)
    (defun foo::mysym (a b ) (+ a b))

    ;; File # 2
    ;; Compiling or loading this file will signal a warning
    ;; (for compilation)
    ;; or an error (for loading) if the BAR package is definition
    ;; locked, because
    ;; the FOO package is not an implementation package
    ;; of the BAR package.
    (in-package :foo)
    (defun bar::my-other-sym (c) (sqrt c))

## 6.4 Package locked errors

The following script shows what happens when you try to perform a protected action on a package-locked package. Here we try to export the symbol `excl::*debug-enclose-printer-errors*` from the `excl` package.

    USER(3): (export 'excl:: *debug-enclose-printer-errors*
                     (find-package :excl))
    Error: #<The EXCL package> is locked against changes by EXPORT.
    [condition type: PACKAGE-LOCKED-ERROR]

    Restart actions (select using :continue):
    0: Allow EXPORT to modify #<The EXCL package>.
    [1c] USER(4):

The next script shows what happens when you try to define a function on a symbol in a package-definition-locked package. We try to define a function on the symbol `excl:*read-init-files*`. We chose this admittedly strange example to make clear that a symbol need not already have a function definition (the symbol in question does not) in order for an error to be signaled.

    USER(18): (defun excl:*read-init-files* nil nil)
    Error: Attempt to make a FUNCTION definition for the name
    EXCL:*READ-INIT-FILES*. This name is in
    the EXCL package and defining it is a violation for
    portable programs. The package EXCL has
    PACKAGE-LOCK-DEFINITIONS set, which causes the system
    to check for this violation.
    [condition type: PACKAGE-LOCKED-ERROR]

    Restart actions (select using :continue):
    0: Set the FUNCTION definition of the name
    EXCL:*READ-INIT-FILES* anyway.
    [1c] USER(19):

In each case, the error has condition type package-locked-error and in each case the error is continuable. By entering :continue 0, the requested action (exporting the symbol or defining the function) will take place.

Note however that package locking is in place for a reason: changing a system-supplied package or defining (or particularly redefining) a function on a symbol in a system-supplied package can cause Lisp to fail because assumptions about the package are violated.

Obviously there are times when changing a package or the definition on a symbol is the right thing to do. If, for example, we instruct you to make some change (say, export a symbol accidentally left off an export list), we are guaranteeing that doing so will not have adverse consequences.

## 6.5 Locally circumventing package locked errors

The variable `*enable-package-locked-errors*` and macro without-package-locks can be used to prevent package-locked-errors (of either type -- ordinary locks and definition locks) without actually unlocking a package.

When `*enable-package-locked-errors*` is true, executing code that violates package-locking or package-definition-locking will signal errors and compiling such code will signal warnings as described above. When it is `nil`, such code will execute without package-locked-errors or compile-time warnings.

The macro without-package-locks, which takes one or more forms as its arguments, evaluates those forms with `*enable-package-locked-errors*` bound to `nil`.

## 6.6 The packages locked by default

For symbols in the `common-lisp` package, all of the actions prevented by package locking and package definition locking are explicitly restricted by the ANSI specification (see sections 11.1.2.1.2 and 11.1.2.1.2.1). The `common-lisp` package is locked and definition locked as are a number of Allegro CL packages, including

        aclmop
        aclwin (Windows only)
        clos
        cltl1
        common-graphics (Windows only)
        common-lisp
        compiler
        cross-reference
        debugger
        defsystem
        excl
        excl.scm
        foreign-functions
        inspect
        lep
        multiprocessing
        profiler
        system
        top-level

## 6.7 Justification for package locking

For the `common-lisp` package, the restrictions of both package-locks and package-lock-definitions locks are compliant with the ANSI standard. Other system-provided packages in Allegro CL are also locked, for the same reasons that the `common-lisp` package is locked.

Writers of application packages may want to lock their packages as well, especially if the package may be used by other packages written later. Package locks can detect inadvertent name collisions before they cause program failures. The following forms will package-lock and package-definition-lock the package `foo`. The same forms, with `nil` instead of `t`, unlock the package.

    (setf (excl:package-lock (find-package :foo)) t)
    (setf (excl:package-definition-lock (find-package :foo)) t)

Copyright (c) 1998-2019, Franz Inc. Oakland, CA., USA. All rights reserved.
This page was not revised from the 8.2 page.
Created 2012.5.30.

ToC | DocOverview | CGDoc | RelNotes | FAQ | Index | PermutedIndex
| Allegro CL version 9.0 Unrevised from 8.2 to 9.0. 8.2 version