symbol-namespaces
2013-01-28
Defines a new kind of package that's named by a symbol rather than a string and that maps from existing symbols to their respective "implicitly managed" counterparts. The motivating use-case is to conceptually allow multiple definitions of the same kind on a single symbol, without conflicts.
Author
Jean-Philippe Paradis <hexstream@gmail.com>
License
Public Domain
Project's home: http://www.hexstreamsoft.com/projects/symbol-namespaces/
Defines a new kind of package that's named by a symbol rather than a
string and that maps from existing symbols to their respective
"implicitly managed" counterparts. The motivating use-case is to
conceptually allow multiple definitions of the same kind on a single
symbol, without conflicts.
PACKAGES
--------
symbol-namespaces exports a single package called SYMBOL-NAMESPACES,
also nicknamed SYMSPACES and SYMSPACE. This package is designed for
explicit qualification of symbols, such as symspace:namespace.
Don't (:use)!
(In this documentation, "namespace" means "symbol-namespace".)
API Overview
------------
The only strict guarantee obeyed by all namespace classes is that they
inherit from symspace:namespace and implement symspace:find-symbol and
symspace:intern-symbol.
Namespace classes may also inherit from symspace:packages, in which
case they also support at least the symspace:find-package and
symspace:intern-package operations.
The main operators of interest for "normal" users of the library are:
- Macro symspace:define defines a namespace and gives it a global name
(symbol), or redefines an existing one;
- Function symspace:locate retrieves a namespace by name;
- Generic Function symspace:find-symbol retrieves the "implicitly
managed" counterpart of a symbol in a namespace, if there is one, or
else returns NIL.
- Generic Function symspace:intern-symbol attempts to
symspace:find-symbol, and if the search is unsuccessful, creates and
returns an appropriate implicitly managed counterpart for the
symbol.
The rest of the API mostly has to do with making it easy to define
custom kinds of namespaces with extended behavior.
For simple uses, it's usually enough to subclass
symspace:standard-namespace and refine behavior by adding new methods
on appropriate generic functions.
For heavier customization, one can subclass symspace:namespace
directly, and define appropriate methods to implement the contract of
generic functions. It's easy to inherit standard pieces of state and
behavior with the provided mixins. symspace:standard-namespace really
just inherits from such mixins.
API Details
-----------
Macro symspace:define name &body options
=> new-or-redefined-namespace
Defines a namespace and gives it a global NAME (symbol),
or redefines an existing one.
The expansion calls symspace:ensure with the NAME and the OPTIONS,
converted from an alist to a plist. If the :class option is specified,
it must have only one argument, which is the class designator which
will be forwarded to symspace:ensure. Otherwise, the default is
symspace:standard-namespace. symspace:standard-namespace doesn't
support any options other than :class, but other subclasses of
symspace:namespace might. In that case, the value of the option in the
plist will be a list of the CDR of the option. For instance, an option
of (:option 1 2 3) would produce ":option (1 2 3)" in the plist.
Neither the option keys nor values are evaluated.
Function symspace:ensure name
&rest keys &key (class 'symspace:standard-namespace) &allow-other-keys
=> new-or-redefined-namespace
Creates a new namespace named NAME, or redefines it if it already
exists.
If a new namespace is created, it will be of class CLASS and the other
KEYS are passed to MAKE-INSTANCE.
If a namespace with that name is already registered, then if the CLASS
is different than the class of the existing instance, CHANGE-CLASS is
called with the CLASS and other KEYS. If the CLASS is the same, then
REINITIALIZE-INSTANCE is called with the instance and the other KEYS.
Accessor symspace:LOCATE name &key (errorp t)
=> namespace-or-nil
Returns the namespace registered with name NAME. If there is no
registered namespace with name NAME, then an error is signaled if
ERRORP is true, else NIL is returned.
Generic Function symspace:NAME
=> name
Retrieves the name of a namespace. Typically implemented by
symspace:name-mixin.
Mixin Class symspace:NAME-MIXIN
Provides a slot of type SYMBOL, filled by initarg :name, whose value
is retrieved by symspace:name. Also provides a PRINT-OBJECT method
that includes the name of the namespace in its output.
Marker Class symspace:NAMESPACE
All namespace kinds inherit from this class. At least
symspace:find-symbol and symspace:intern-symbol are supported.
symspace:standard-namespace provides a ready-to-use implementation.
Generic Function symspace:INTERN-SYMBOL symbol symbol-namespace
=> symbol
Argument precedence order: symbol-namespace, symbol
Attempts to symspace:FIND-SYMBOL, and if the search is unsuccessful,
creates and returns an appropriate implicitly managed counterpart for
the symbol.
Generic Function symspace:FIND-SYMBOL symbol symbol-namespace
=> symbol-or-nil
Argument precedence order: symbol-namespace, symbol
Retrieves the "implicitly managed" counterpart of a symbol in a
namespace, if there is one, or else returns NIL.
Marker Class symspace:PACKAGES
Namespace classes inheriting from this class implicitly manage some
packages internally, and support the symspace:find-package and
symspace:intern-package operations. A related operation that might be
supported is symspace:make-package-name, potentially used by
symspace:intern-package.
See symspace:packages-identity-mixin and symspace:packages-name-mixin
for built-in implementations. symspace:standard-namespace uses the
former.
Generic Function symspace:INTERN-PACKAGE package symbol-namespace
=> package
Argument precedence order: symbol-namespace, package
Attempts to symspace:FIND-PACKAGE, and if the search is unsuccessful,
creates and returns an appropriate implicitly managed counterpart for
the package.
Generic Accessor symspace:FIND-PACKAGE package symbol-namespace
=> package-or-nil
Argument precedence order: symbol-namespace, package
Retrieves the "implicitly managed" counterpart of a package in a
namespace, if there is one, or else returns NIL.
Generic Function symspace:MAKE-PACKAGE-NAME package symbol-namespace
=> name
Computes an appropriate package name for a new "implicitly managed"
counterpart of PACKAGE.
Mixin Class symspace:PACKAGES-IDENTITY-MIXIN
Implements symspace:packages. Packages are found and interned on the
basis of their identity (EQ comparison of packages). This is what
symspace:standard-namespace uses.
Mixin Class symspace:PACKAGES-NAME-MIXIN
Implements symspace:packages. Packages are found and interned on the
basis of equality of their package names.
Class symspace:STANDARD-NAMESPACE
A ready-to-use implementation of symspace:namespace. Simply inherits
from symspace:name-mixin, symspace:packages-identity-mixin, and
symspace:namespace.
This library is in the Public Domain.
See the UNLICENSE file for details.