The defpackage-plus Reference Manual

Next: , Previous: , Up: (dir)   [Contents][Index]

The defpackage-plus Reference Manual

This is the defpackage-plus Reference Manual, version 1.0, generated automatically by Declt version 4.0 beta 2 "William Riker" on Mon Aug 15 04:25:39 2022 GMT+0.

Table of Contents


1 Introduction

defpackage-plus

DEFPACKAGE-PLUS is an extensible DEFPACKAGE variant with predictable cross-platform behavior and some utilities useful for versioning. (See Versioning below.)

defpackage+

The DEFPACKAGE+ macro may be used similarly to DEFPACKAGE. The package :defpackage+-user-<version> is provided for easily accessing this and other defpackage-plus functionality. For example:

(in-package :defpackage+-user-1)

(defpackage+ :my-package
  (:use #:cl #:alexandria)
  (:export #:some-symbol))

Options

The following options are available. Each of these are implemented as a call to the corresponding package manipulation function. Repeated evaluations of the DEFPACKAGE+ form are the same as repeatedly calling each function in sequence, and the behavior of such is stated below:

Package definition itself (i.e. the (defpackage+ NAME) part) happens via ENSURE-PACKAGE; the package will be created unless one already exists with the given name.

Differences with defpackage

For the most part, defpackage+ is simply a more convenient defpackage. You can likely use them interchangeably. However, there are some notable differences:

Extensibility

All options to defpackage+ are implemented via calls to DEFPACKAGE+-DISPATCH:

defpackage+-dispatch OPTION PARAMS PACKAGE

OPTION is the car of the option, PARAMS is the cdr, and PACKAGE is the name of the package as specified to defpackage+. Specialize on OPTION. Keywords and symbols from COMMON-LISP are reserved by defpackage-plus for internal use.

Note, this function does not return an expansion as for a macro. Rather, defpackage+ itself expands into a series of calls to this function. This makes extensibility much easier.

(defpackage+ :my-package
  (:use #:cl)
  (:export #:symbol))

;; expands to:

(eval-when (:compile-toplevel :load-toplevel :execute)
  (ensure-package ':my-package)
  (defpackage+-dispatch ':use '(#:cl) ':my-package)
  (defpackage+-dispatch ':export '(#:symbol) ':my-package))

Package Manipulation Functions

Numerous additional functions are provided in addition to what Common Lisp already provides. These are identical to, and used to implement, the corresponding defpackage+ options.

Idioms

There is nothing specific about versions provided per se, but following the stated idiom should provide your users with a stable API as well as the ability to improve the API without conflicts.

Versioning

A common occurrence: you want to alter your API in some incompatible way. Change how a function works. Alter a default. Not a huge change, but it would be a big improvement. You have a few options:

This is where defpackage-plus comes in:

(defpackage+ :system-1
  ...
  (:export #:function-1 #:function-2 #:function-3))

(defpackage+ system-2
  ...
  (:inherit-except :system-1 #:function-3)
  (:export #:function-3))

Simply append an appropriate version number to your package. When you wish to introduce significant (i.e., API-incompatible) changes, simply create a new package with defpackage+ with a higher version, and use the various :inherit options to push forward anything that will not change.

This does nothing fancy: it simply imports and exports all external symbols from :system-1, except FUNCTION-3. At this point, a different FUNCTION-3 is exported, and it may be defined in whatever new way that's desired.

Both versions may exist simultaneously, even share code, and vary in whatever way the developer needs. Simple, but effective.

For example:

(defpackage+ my-package-1
  (:use #:cl)
  (:export function-1 function-2))

(defpackage+ my-package-2
  (:use #:cl)
  (:inherit-from :my-package-1 #:function-1)
  (:export #:function-3))

In this case FUNCTION-3 may be an entirely different interface intended to replace FUNCTION-2. However, FUNCTION-1 will remain unchanged and available.

Users will simply do the following:

(defpackage+ user-package-1
  (:use ... #:my-package-2))

This will ensure they see only the relevant 2 symbols. Of course, users using defpackage+ is not strictly necessary, but it may be useful in the following examples.

Not all users may, of course, wish to import all of your symbols into their packages, for all the regular reasons. And typing my-package-2: before every symbol may be a bit onerous to some. The following is also a possibility:

(defpackage+ user-apis-1
  ;; Alternatively we could simply (:inherit #:my-package-2 #:some-other-3)
  (:inherit-from #:my-package-2 symbol-1 ...)
  (:inherit-from #:some-other-3 another-symbol ...))

(defpackage+ :user-package-1
  (:use ... :user-apis-1))

There are many ways to combine this based on preference, of course. If package-local nicknames are available, this may provide the cleanest option, but not all Lisps support this.

What not to do:

Leave off version numbers. It may occur to some people to simply maintain "old" versions with version numbers, and the "latest" version without:

;;; This is a TERRIBLE idea.  You just defeated the point:
(defpackage+ my-package
  (:inherit-from :my-package-3 ...))

(defpackage+ my-package-3
  (:inherit-from :my-package-2 ...))

...

This resolves nothing; changing the current package will still break everyone's code, defeating the point. Requiring people to figure out after the fact which version works with their code is even worse. You change things wildly. Much code rot ensues.

Import everything always. It may occur to you to do the following, if you are unfamiliar with how packages and symbols work:

(defpackage my-package-1
  ...
  (:export #:function-1))

(defpackage my-package-2
  ...
  (:inherit my-package-1))

;;; This is BAD.  You just broke 1:
(in-package :my-package-2)

(defun function-1 (...)
  ...)

The fact FUNCTION-1 is being redefined while "in" MY-PACKAGE-2 is irrelevant: FUNCTION-1 is still imported from MY-PACKAGE-1, and you are redefining the old function here. What you should have done was :inherit-except and exported a new version.


2 Systems

The main system appears first, followed by any subsystem dependency.


Previous: , Up: Systems   [Contents][Index]

2.1 defpackage-plus

Extensible DEFPACKAGE with version support

Author

Ryan Pavlik

License

BSD-2-Clause

Version

1.0

Dependency

alexandria (system).

Source

defpackage-plus.asd.

Child Components

3 Files

Files are sorted by type and then listed depth-first from the systems components trees.


Previous: , Up: Files   [Contents][Index]

3.1 Lisp


Next: , Previous: , Up: Lisp   [Contents][Index]

3.1.1 defpackage-plus/defpackage-plus.asd

Source

defpackage-plus.asd.

Parent Component

defpackage-plus (system).

ASDF Systems

defpackage-plus.

Packages

defpackage-plus.asdf.


3.1.2 defpackage-plus/package.lisp

Source

defpackage-plus.asd.

Parent Component

defpackage-plus (system).

Packages

3.1.3 defpackage-plus/utility.lisp

Dependency

package.lisp (file).

Source

defpackage-plus.asd.

Parent Component

defpackage-plus (system).

Public Interface

3.1.4 defpackage-plus/ensure.lisp

Dependency

utility.lisp (file).

Source

defpackage-plus.asd.

Parent Component

defpackage-plus (system).

Public Interface

3.1.5 defpackage-plus/inherit.lisp

Dependency

ensure.lisp (file).

Source

defpackage-plus.asd.

Parent Component

defpackage-plus (system).

Public Interface
Internals

3.1.6 defpackage-plus/local-nicknames.lisp

Dependency

inherit.lisp (file).

Source

defpackage-plus.asd.

Parent Component

defpackage-plus (system).

Public Interface

defpackage+-dispatch (method).

Internals

3.1.7 defpackage-plus/defpackage-plus.lisp

Dependency

local-nicknames.lisp (file).

Source

defpackage-plus.asd.

Parent Component

defpackage-plus (system).

Public Interface

3.1.8 defpackage-plus/package-plus.lisp

Dependency

defpackage-plus.lisp (file).

Source

defpackage-plus.asd.

Parent Component

defpackage-plus (system).


4 Packages

Packages are listed by definition order.


Next: , Previous: , Up: Packages   [Contents][Index]

4.1 defpackage+-user-1

Source

package.lisp.

Use List

4.2 defpackage-plus.asdf

Source

defpackage-plus.asd.

Use List
  • asdf/interface.
  • common-lisp.

4.3 defpackage-plus-1

Source

package.lisp.

Nickname

defpackage+-1

Use List
  • alexandria.
  • common-lisp.
Used By List

defpackage+-user-1.

Public Interface
Internals

5 Definitions

Definitions are sorted by export status, category, package, and then by lexicographic order.


Next: , Previous: , Up: Definitions   [Contents][Index]

5.1 Public Interface


5.1.1 Macros

Macro: defpackage+ (package-name &body options)
Package

defpackage-plus-1.

Source

defpackage-plus.lisp.


5.1.2 Ordinary functions

Function: ensure-export (export-list &optional package)
Package

defpackage-plus-1.

Source

ensure.lisp.

Function: ensure-export-only (export-list &optional package)
Package

defpackage-plus-1.

Source

ensure.lisp.

Function: ensure-export-warning (export-list &optional package)
Package

defpackage-plus-1.

Source

ensure.lisp.

Function: ensure-nicknames (nickname-list &optional package)
Package

defpackage-plus-1.

Source

ensure.lisp.

Function: ensure-package (package-name)
Package

defpackage-plus-1.

Source

ensure.lisp.

Function: ensure-use-only (use-list &optional package)
Package

defpackage-plus-1.

Source

ensure.lisp.

Function: import-external-from (from-package symbol-name-list &optional package)

Import symbols in ‘SYMBOL-NAME-LIST‘ from ‘FROM-PACKAGE‘ into ‘PACKAGE‘, but only if they are external to ‘FROM-PACKAGE‘. It is an error if any symbol named in ‘SYMBOL-NAME-LIST‘ is not accessible in ‘FROM-PACKAGE‘, or if the symbol is not external to ‘FROM-PACKAGE‘.

Package

defpackage-plus-1.

Source

inherit.lisp.

Function: import-from (from-package symbol-name-list &optional package)

Import symbols in ‘SYMBOL-NAME-LIST‘ from ‘FROM-PACKAGE‘ into ‘PACKAGE‘. It is an error if any symbol named in ‘SYMBOL-NAME-LIST‘ is not accessible in ‘FROM-PACKAGE‘.

Package

defpackage-plus-1.

Source

inherit.lisp.

Function: inherit-from (from-package symbol-list &optional package)

Import/export some external symbols from ‘FROM-PACKAGE‘. This is like ‘IMPORT-FROM‘, except symbols in ‘SYMBOL-LIST‘ are *also exported* from ‘PACKAGE‘. It is an error if any symbols in ‘SYMBOL-LIST‘ are not external to ‘FROM-PACKAGE‘.

Package

defpackage-plus-1.

Source

inherit.lisp.

Function: inherit-package (from-package &optional package)

Import/export *all* external symbols from ‘FROM-PACKAGE‘. This is like ‘USE-PACKAGE‘ and ‘INHERIT-FROM‘ with all symbols external to ‘FROM-PACKAGE‘ specified.

Note that this only applies to symbols exported *when called*. Future symbols exported from ‘FROM-PACKAGE‘ will not also be exported from ‘PACKAGE‘ unless this function is called again.

Package

defpackage-plus-1.

Source

inherit.lisp.

Function: inherit-package-except (from-package except-symbols &optional package)

Import/export all symbols from ‘FROM-PACKAGE‘ *except* those specified by ‘EXCEPT-SYMBOLS‘.

Package

defpackage-plus-1.

Source

inherit.lisp.

Function: package-external-symbols (package)

=> LIST-OF-SYMBOLS

Return a new list of symbols external to ‘PACKAGE‘

Package

defpackage-plus-1.

Source

utility.lisp.

Function: package-symbols (package)

=> LIST-OF-SYMBOLS

Return a new list of symbols accessible from ‘PACKAGE‘. Like ‘DO-SYMBOLS‘, this may include the same symbol more than once.

Package

defpackage-plus-1.

Source

utility.lisp.

Function: shadowing-import-from (from-package symbol-name-list &optional package)

Shadowing-import symbols in ‘SYMBOL-NAME-LIST‘ from ‘FROM-PACKAGE‘ into ‘PACKAGE‘. It is an error if any symbol named in ‘SYMBOL-NAME-LIST‘ is not accessible in ‘FROM-PACKAGE‘.

Package

defpackage-plus-1.

Source

inherit.lisp.


5.1.3 Generic functions

Generic Function: defpackage+-dispatch (option parameters package-name)

This function is called for every form in the body
of ‘DEFPACKAGE+‘. The ‘CAR‘ of each form is the ‘OPTION‘ parameter, which methods should specialize on. The ‘CDR‘ of the list is ‘PARAMETERS‘.

All keywords and symbols from ‘COMMON-LISP‘ are reserved for use by defpackage-plus; user methods should **not** specialize on these.

Package

defpackage-plus-1.

Source

defpackage-plus.lisp.

Methods
Method: defpackage+-dispatch ((option (eql :intern)) params package)
Method: defpackage+-dispatch ((option (eql :nicknames)) params package)
Method: defpackage+-dispatch ((option (eql :shadowing-import-from)) params package)
Method: defpackage+-dispatch ((option (eql :shadow)) params package)
Method: defpackage+-dispatch ((option (eql :import-except-conflicts)) params package)
Method: defpackage+-dispatch ((option (eql :import-except)) params package)
Method: defpackage+-dispatch ((option (eql :import-external)) params package)
Method: defpackage+-dispatch ((option (eql :import-from)) params package)
Method: defpackage+-dispatch ((option (eql :inherit-except)) params package)
Method: defpackage+-dispatch ((option (eql :inherit)) params package)
Method: defpackage+-dispatch ((option (eql :inherit-from)) params package)
Method: defpackage+-dispatch ((option (eql :documentation)) params package)
Method: defpackage+-dispatch ((option (eql :export-warning)) params package)
Method: defpackage+-dispatch ((option (eql :export-only)) params package)
Method: defpackage+-dispatch ((option (eql :export)) params package)
Method: defpackage+-dispatch ((option (eql :use-only)) params package)
Method: defpackage+-dispatch ((option (eql :use)) params package)
Method: defpackage+-dispatch ((option (eql :local-nicknames)) params package)
Source

local-nicknames.lisp.


5.2 Internals


Next: , Previous: , Up: Internals   [Contents][Index]

5.2.1 Special variables

Special Variable: *from-package*
Package

defpackage-plus-1.

Source

inherit.lisp.


Previous: , Up: Internals   [Contents][Index]

5.2.2 Ordinary functions

Function: add-local-nickname (package nickname local-to)
Package

defpackage-plus-1.

Source

local-nicknames.lisp.

Function: assert-symbol-p (symbol status function-name)
Package

defpackage-plus-1.

Source

inherit.lisp.

Function: ensure-global-nickname (package nickname)
Package

defpackage-plus-1.

Source

local-nicknames.lisp.

Function: external-symbol-p (symbol status function-name)
Package

defpackage-plus-1.

Source

inherit.lisp.

Function: import-except-conflics (from-package &optional package)

Import all symbols from ‘FROM-PACKAGE‘ *except* symbols that would conflict with those in ‘PACKAGE‘.

Package

defpackage-plus-1.

Source

inherit.lisp.

Function: import-package-except (from-package except-symbols &optional package)

Import all symbols from ‘FROM-PACKAGE‘ *except* those specified by ‘EXCEPT-SYMBOLS‘.

Package

defpackage-plus-1.

Source

inherit.lisp.

Function: map-symbol-names (function symbol-name-list from-package)
Package

defpackage-plus-1.

Source

inherit.lisp.

Function: symbol-check (check-function function-name)
Package

defpackage-plus-1.

Source

inherit.lisp.


Appendix A Indexes


Next: , Previous: , Up: Indexes   [Contents][Index]

A.1 Concepts


Next: , Previous: , Up: Indexes   [Contents][Index]

A.2 Functions

Jump to:   A   D   E   F   G   I   M   P   S  
Index Entry  Section

A
add-local-nickname: Private ordinary functions
assert-symbol-p: Private ordinary functions

D
defpackage+: Public macros
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions
defpackage+-dispatch: Public generic functions

E
ensure-export: Public ordinary functions
ensure-export-only: Public ordinary functions
ensure-export-warning: Public ordinary functions
ensure-global-nickname: Private ordinary functions
ensure-nicknames: Public ordinary functions
ensure-package: Public ordinary functions
ensure-use-only: Public ordinary functions
external-symbol-p: Private ordinary functions

F
Function, add-local-nickname: Private ordinary functions
Function, assert-symbol-p: Private ordinary functions
Function, ensure-export: Public ordinary functions
Function, ensure-export-only: Public ordinary functions
Function, ensure-export-warning: Public ordinary functions
Function, ensure-global-nickname: Private ordinary functions
Function, ensure-nicknames: Public ordinary functions
Function, ensure-package: Public ordinary functions
Function, ensure-use-only: Public ordinary functions
Function, external-symbol-p: Private ordinary functions
Function, import-except-conflics: Private ordinary functions
Function, import-external-from: Public ordinary functions
Function, import-from: Public ordinary functions
Function, import-package-except: Private ordinary functions
Function, inherit-from: Public ordinary functions
Function, inherit-package: Public ordinary functions
Function, inherit-package-except: Public ordinary functions
Function, map-symbol-names: Private ordinary functions
Function, package-external-symbols: Public ordinary functions
Function, package-symbols: Public ordinary functions
Function, shadowing-import-from: Public ordinary functions
Function, symbol-check: Private ordinary functions

G
Generic Function, defpackage+-dispatch: Public generic functions

I
import-except-conflics: Private ordinary functions
import-external-from: Public ordinary functions
import-from: Public ordinary functions
import-package-except: Private ordinary functions
inherit-from: Public ordinary functions
inherit-package: Public ordinary functions
inherit-package-except: Public ordinary functions

M
Macro, defpackage+: Public macros
map-symbol-names: Private ordinary functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions
Method, defpackage+-dispatch: Public generic functions

P
package-external-symbols: Public ordinary functions
package-symbols: Public ordinary functions

S
shadowing-import-from: Public ordinary functions
symbol-check: Private ordinary functions

Jump to:   A   D   E   F   G   I   M   P   S  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.3 Variables

Jump to:   *  
S  
Index Entry  Section

*
*from-package*: Private special variables

S
Special Variable, *from-package*: Private special variables

Jump to:   *  
S  

Previous: , Up: Indexes   [Contents][Index]

A.4 Data types

Jump to:   D   E   F   I   L   P   S   U  
Index Entry  Section

D
defpackage+-user-1: The defpackage+-user-1 package
defpackage-plus: The defpackage-plus system
defpackage-plus-1: The defpackage-plus-1 package
defpackage-plus.asd: The defpackage-plus/defpackage-plus․asd file
defpackage-plus.asdf: The defpackage-plus․asdf package
defpackage-plus.lisp: The defpackage-plus/defpackage-plus․lisp file

E
ensure.lisp: The defpackage-plus/ensure․lisp file

F
File, defpackage-plus.asd: The defpackage-plus/defpackage-plus․asd file
File, defpackage-plus.lisp: The defpackage-plus/defpackage-plus․lisp file
File, ensure.lisp: The defpackage-plus/ensure․lisp file
File, inherit.lisp: The defpackage-plus/inherit․lisp file
File, local-nicknames.lisp: The defpackage-plus/local-nicknames․lisp file
File, package-plus.lisp: The defpackage-plus/package-plus․lisp file
File, package.lisp: The defpackage-plus/package․lisp file
File, utility.lisp: The defpackage-plus/utility․lisp file

I
inherit.lisp: The defpackage-plus/inherit․lisp file

L
local-nicknames.lisp: The defpackage-plus/local-nicknames․lisp file

P
Package, defpackage+-user-1: The defpackage+-user-1 package
Package, defpackage-plus-1: The defpackage-plus-1 package
Package, defpackage-plus.asdf: The defpackage-plus․asdf package
package-plus.lisp: The defpackage-plus/package-plus․lisp file
package.lisp: The defpackage-plus/package․lisp file

S
System, defpackage-plus: The defpackage-plus system

U
utility.lisp: The defpackage-plus/utility․lisp file

Jump to:   D   E   F   I   L   P   S   U