in-nomine
2024-10-12
Utilities for extensible namespaces in Common Lisp.
Upstream URL
Author
License
In Nomine
The beginning of wisdom is to call things by their proper name.
-- Confucius
This is a utility for creating, accessing, and managing custom namespaces in Common Lisp. Originally started as a fork of LISP-NAMESPACE
, it became its own piece of software that is somewhat backwards compatible with it.
Syntax differences from LISP-NAMESPACE
- Removed macros
NAMESPACE-LET
andNSLET
, - Removed the
DEFINE-NAMESPACE
option to automatically generateNAMESPACE-LET
-based binding macros, - Added boundp and makunbound functions for namespace names,
- Moved hash tables for bindings and documentation from being implicitly created as variables to slots of the namespaces objects themselves (unless requested otherwise),
- Added long form of
DEFINE-NAMESPACE
to customize behavior of generated namespaces, - Exported namespace objects and their readers.
Manual
A namespace is a second-class concept in Common Lisp and refers to concept that allows to associate names of some sort with objects of some sort.
Common Lisp has a lot of namespaces whose keys can come in various shapes:
- interned symbols (package-and-string tuples),
- variables and symbol macros (symbols),
- functions and macros (symbols),
- compiler macros (symbols),
SETF
expansions (Lisp forms),- classes, conditions, and types (symbols),
- slot names (symbols),
- method combinations (symbols),
- block names (symbols),
- tagbody tags (symbols and integers)
- catch tags (any Lisp objects),
- restarts (symbols),
- packages (strings),
- modules (strings),
- logical pathname hosts (strings),
- reader macros (characters),
- character codes (characters),
- character names (strings),
- characters (only true on some implementations) (integers),
- ...
- ASDF systems (lowercase strings),
- ... (people can make new ones!)
This system is a utility to bring a first-class implementation of the concept of namespaces along with utilities to customize and manage them.
The heart of the facility is the DEFINE-NAMESPACE
macro, which comes in two forms: short (syntax-compatible with LISP-NAMESPACE:DEFINE-NAMESPACE
and with mostly compatible effects) and long form (allowing for greater behavior customization).
DEFINE-NAMESPACE
, by default, generates functions for accessing the namespace, a condition signaled whenever an access to an unbound name is attempted, a type which denotes the values permissible in a namespace, and documentation types.
By default, names are symbols and compared via EQ
. This behavior is consistent with the way Common Lisp names variables and classes.
IN-NOMINE> (define-namespace thing) #<NAMESPACE THING (0 bindings)> IN-NOMINE> (setf (symbol-thing 'foo) 42 (symbol-thing 'bar) :keyword (symbol-thing 'baz) *readtable*) #<READTABLE {1000022CA3}> IN-NOMINE> (mapcar #'symbol-thing '(foo bar baz)) (42 :KEYWORD #<READTABLE {1000022CA3}>)
It is possible to customize this behavior, though, and get e.g. a namespace in which names are non-negative numbers.
IN-NOMINE> (define-namespace player ;; Use numbers as hash table keys :name-type unsigned-byte ;; Numbers are EQL-comparable :hash-table-test eql :accessor player-no) #<NAMESPACE PLAYER (0 bindings)> IN-NOMINE> (setf (player-no 8) :jerry (player-no 0) :thomas (player-no 2) :michael) :MICHAEL IN-NOMINE> (player-no 8) :JERRY IN-NOMINE> (player-no 1) ;; Error: Name 1 is unbound in namespace PLAYER. ;; [Condition of type UNBOUND-PLAYER]
It is possible to utilize different name types along with all four standard hash table keys and produce namespaces with different possible name values. Examples:
EQ
for symbols,EQL
for numbers and characters,EQUAL
for strings or lists,EQUALP
for strings without case sensitivity.
It is possible to define a definer macro for the namespace.
IN-NOMINE> (define-namespace game :definer-name defgame :definer cons) #<NAMESPACE GAME (0 bindings)> IN-NOMINE> (defgame some-game 8 3) (8 . 3) IN-NOMINE> (symbol-game 'some-game) (8 . 3)
In Nomine by default provides documentation types with the same names as namespace names.
IN-NOMINE> (setf (documentation 8 'player) "The best player ever.") "The best player ever." IN-NOMINE> (documentation 8 'player) "The best player ever."
In addition, In Nomine hooks into implementation-defined CL:DESCRIBE
in order to provide information about namespace bindings.
IN-NOMINE> (describe 'foo) IN-NOMINE::FOO [symbol] Symbol FOO is bound in namespace THING: Value: 42 (undocumented) ; No value IN-NOMINE> (describe 8) 8 [fixnum] 8 is bound in namespace PLAYER: Value: :JERRY Documentation: The best player ever. ; No value
API
Packages
Package IN-NOMINE
Loaded via (asdf:load-system :in-nomine)
.
Utilities for defining additional namespaces in Common Lisp.
Common Lisp is a Lisp-N, which means that it has a different namespaces for variables, functions, types, and so on. Users can also define their own namespaces, and In Nomine is a toolkit for making that process easier.
Namespace definition and management
Macro DEFINE-NAMESPACE
Defines a new namespace object in the global namespace namespace along with a series of functions, types, conditions, and type proclamations for accessing this namespace.
Two forms of this macro are provided:
- short form:
(DEFINE-NAMESPACE NAME &OPTIONAL VALUE-TYPE BINDING DOCUMENTATION)
NAME
- a symbol naming the namespace,VALUE-TYPE
- a type specifier for values bound in this namespace,BINDING
- deprecated, only present for syntax compatibility withLISP-NAMESPACE
; must beNIL
when provided,DOCUMENTATION
- documentation string for the namespace object.
- For name
FOO
, the following are generated:- Accessor functions
SYMBOL-FOO
and(SETF SYMBOL-FOO)
, - Makunbound function
FOO-MAKUNBOUND
, - Boundp function
FOO-BOUNDP
, - Type proclamations for the four functions above,
- Condition type
UNBOUND-FOO
, - Type
FOO-TYPE
denoting the specifiedVALUE-TYPE
, - Documentation methods with documentation type specialized on
(EQL 'FOO)
.
- Accessor functions
- long form:
(DEFINE-NAMESPACE NAME &KEY NAME-TYPE VALUE-TYPE ACCESSOR CONDITION-NAME TYPE-NAME MAKUNBOUND-SYMBOL BOUNDP-SYMBOL DOCUMENTATION-TYPE ERROR-WHEN-NOT-FOUND-P ERRORP-ARG-IN-ACCESSOR-P DEFAULT-ARG-IN-ACCESSOR-P HASH-TABLE-TEST BINDING-TABLE-VAR DOCUMENTATION-TABLE-VAR DOCUMENTATION DEFINER-NAME DEFINER)
NAME
- a symbol naming the namespace,NAME-TYPE
- a type specifiers for keys bound in this namespace,VALUE-TYPE
- a type specifier for values bound in this namespace,ACCESSOR
- a symbol naming the accessor functions, orNIL
if no such accessor should be defined,CONDITION-NAME
- a symbol naming the condition type signaled when an attempt is made to access an unbound name, orNIL
if no such accessor should be defined,TYPE-NAME
- a symbol naming the type for the namespace values, orNIL
if no such type should be defined,MAKUNBOUND-SYMBOL
- symbol naming the namespace makunbound function, orNIL
if no such function should be defined,BOUNDP-SYMBOL
- a symbol naming the namespace boundp function, orNIL
if no such function should be defined,DOCUMENTATION-TYPE
- a symbol naming the documentation type for the namespace values, orNIL
if no such documentation should be defined,ERROR-WHEN-NOT-FOUND-P
- a boolean stating whether a reader function should signal an error if it attempts to access an unbound name,ERRORP-ARG-IN-ACCESSOR-P
- a boolean stating whether accessor functions should have an optionalERRORP
argument for stating whether an unbound condition should be signaled when an attempt is made to access an unbound name,DEFAULT-ARG-IN-ACCESSOR-P
- a boolean stating whether accessor functions should have an optionalDEFAULT
argument for automatic setting of unbound values,HASH-TABLE-TEST
- a symbol naming the hash table test of the binding and documentation hash tables of the namespace,BINDING-TABLE-VAR
- a symbol naming the variable whose value shall be the binding table of the namespace, orNIL
if no such variable should be defined,DOCUMENTATION-TABLE-VAR
- a symbol naming the variable whose value shall be the documentation table of the namespace, orNIL
if no such variable should be defined,DOCUMENTATION
- documentation string for the namespace object.DEFINER-NAME
- name of the definer for a definition in the namespace; defaults toDEFINE-[NAME]
if a definer is to be definedDEFINER
- can have one of several forms, defines a macro with name[DEFINER-NAME]
whose lambda list always starts with a gensymed argumentBINDING-NAME
for the name of the defined bindingNIL
- if noDEFINER-NAME
is given, don't define a definer, otherwise define a standard definer with argument listBINDING-NAME OBJECT
that bindsBINDING-NAME
to the result of evaluatingOBJECT
T
- likeNIL
, but also defines a definer ifDEFINER-NAME
has not been supplied[FUNCTION]
,'[FUNCTION]
,#'[FUNCTION]
- define a definer with argument-listBINDING-NAME [LAMBDA-LIST-OF-FUNCTION]
, which bindsBINDING-NAME
to the result of calling[FUNCTION]
on the rest of the arguments(LAMBDA (ARGS) BODY*)
- same as with named functions, but with the given anonymous function(LAMBDA-LIST BODY*)
- the lambda list can be a generalized lambda list; body should evaluate to the code executed to produce the object to bindBINDING-NAME
to
The consequences are undefined if a namespace is redefined in an incompatible way with the previous one.
Function SYMBOL-NAMESPACE
Returns a namespace object with the given global name. Signals UNBOUND-NAMESPACE
unless ERRORP
is set.
Function CLEAR-NAMESPACE
Removes all bindings in the namespace with the given name.
Function NAMESPACE-MAKUNBOUND
Makes the name globally unbound as a namespace regardless of whether the name was previously bound.
Function NAMESPACE-BOUNDP
Returns true if a namespace object with the provided name is globally bound, false otherwise.
Condition Type UNBOUND-NAMESPACE
A subtype of CELL-ERROR
signaled when there is an attempt to access a namespace object that does not exist.
Namespace class and accessors
Class NAMESPACE
A class of namespace objects which represent a Common Lisp namespace.
Function NAMESPACE-NAME
Returns the symbol naming a namespace.
Function NAMESPACE-NAME-TYPE
Returns the type of names that are possible to bind in a namespace.
Function NAMESPACE-VALUE-TYPE
Returns the type of values that are possible to bind in a namespace.
Function NAMESPACE-ACCESSOR
Returns the symbol naming the namespace accessor, or NIL
if no such accessor is defined.
Function NAMESPACE-CONDITION-NAME
Returns the symbol naming the condition type signaled when an attempt is made to access an unbound name, or NIL
if no such condition type is defined
Function NAMESPACE-TYPE-NAME
Returns the symbol naming the type for the namespace values, or NIL
if no such type is defined.
Function NAMESPACE-MAKUNBOUND-SYMBOL
Returns the symbol naming the namespace makunbound function, or NIL
if no such function exists.
Function NAMESPACE-BOUNDP-SYMBOL
Returns the symbol naming the namespace boundp function, or NIL
if no such function exists.
Function NAMESPACE-DOCUMENTATION-TYPE
Returns the symbol naming the documentation type for the namespace values, or NIL
if no such documentation type exists.
Function NAMESPACE-ERROR-WHEN-NOT-FOUND-P
Returns a boolean stating whether a reader function should signal an error if it attempts to access an unbound name.
Function NAMESPACE-ERRORP-ARG-IN-ACCESSOR-P
Returns a boolean stating whether accessor functions should have an optional ERRORP
argument for stating whether an unbound condition should be signaled when an attempt is made to access an unbound name.
Function NAMESPACE-DEFAULT-ARG-IN-ACCESSOR-P
Returns a boolean stating whether accessor functions should have an optional DEFAULT
argument for automatic setting of unbound values.
Function NAMESPACE-HASH-TABLE-TEST
Returns the symbol naming the hash table test of the binding and documentation hash tables of the namespace.
Function NAMESPACE-BINDING-TABLE
Returns the binding hash table, or NIL
if BINDING-TABLE-VAR
is defined or no binding mechanism is defined.
Function NAMESPACE-DOCUMENTATION-TABLE
Returns the documentation hash table, or NIL
if no documentation type is defined.
Function NAMESPACE-BINDING-TABLE-VAR
Returns the symbol naming the variable whose value is the binding table of the namespace, or NIL
if no such variable is defined. Changing the value or dynamically binding this variable will affect the global environment of the namespace.
Function NAMESPACE-DOCUMENTATION-TABLE-VAR
Returns the symbol naming the variable whose value is the documentation table of the namespace, or NIL
if no such variable is defined.
Namespaces
Namespace NAMESPACE
A namespace for managing namespaces.
License
- Copyright (c) 2015 Masataro Asai
- Copyright (c) 2022 Michał "phoe" Herda
Licensed under the LLGPL License.
A man that should call everything by its right name, would hardly pass the streets without being knocked down as a common enemy.
-- Lord Halifax