Skip to content

Commit

Permalink
Add define-conduit-package
Browse files Browse the repository at this point in the history
This will be 5.0.0
  • Loading branch information
tfeb committed Jul 26, 2024
1 parent 574b3aa commit d5bf983
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 3 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 1998-2002, 2020-2023 Tim Bradshaw
Copyright 1998-2002, 2020-2024 Tim Bradshaw

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
Expand Down
45 changes: 44 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,36 @@ Here's a slightly larger example where four packages are involved:
#:onion))
```

### A simpler way using `define-conduit-package`
If all you want to do is define a pure conduit, then `define-conduit-package` provides a shim for `define-package` which makes it simpler and checks for common mistakes. It is exactly like `define-package` except:

- it inserts a `(:use)` clause;
- it checks for `(:use x)` clauses and signals a restartable error if it finds any.

```lisp
(define-conduit-package :org.tfeb.program
(:extends/including :org.tfeb.substrate
#:vegetable)
(:extends :org.tfeb.program-1)
(:extends/excluding :org.tfeb.program-2
#:onion))
```

is equivalent to the final `define-package` form above. The real advantage of this form is:

```lisp
> (define-conduit-package :foo
(:use :cl)
(:extends :cl))
Error: Conduit foo uses other packages
1 (continue) Blunder on with this likely-bogus conduit
2 Use other clauses (interactively: remove the offending clauses)
3 (abort) Return to top loop level 0.
1 > :c 2
```

### Package cloning
Cloning a package is making a package which is 'like' it: all of its internal, external, and shadowing symbols, as well as its used packages will be the same as the package it clones, but in addition any other things asked for by the `defpackage` form will be done. Once a clone is made it lives an independent life to the package it clones: clones are not dynamic, and don't remember what package they were cloned from. Clones can't also be conduits.

Expand Down Expand Up @@ -252,6 +282,14 @@ These clauses are all implemented by a predefined mechanism for `define-package`

In addition the semi-standard `:local-nicknames` clause is passed down to the underlying `defsystem` by default: other clauses like this can be added (see below).

### `define-conduit-package`
`define-conduit-package` provides a slightly simpler way of defining pure conduits. It is exactly like `define-package` but:

- it interpolates a `(:use)` clause;
- it checks the provided clauses for `:use` clauses with a non-empty list of packages, and signals a restartable error, with a restart which offers to expunge these clauses.

So it means you have to type slightly less, and also catches a common mistake.

### Variant package functions, and a utility
These functions call their CL equivalents but also do conduits maintenance.

Expand Down Expand Up @@ -407,9 +445,14 @@ In 2023, I realised that I needed a way of extending `defpackage` for another pu

Much of this is not entirely compatible: I suspect it hurts nobody but me, however. It all smells better after the changes, I think.

### `define-conduit-package` (2024)
I just thought this was useful.

---

Conduit packages is copyright 1998-2002, 2020-2023 by Tim Bradshaw. See `LICENSE` for the license.
Conduit packages is copyright 1998-2002, 2020-2024 by Tim Bradshaw. See `LICENSE` for the license.

---

[^1]: Here and below I have given package names in lower case: they are, of course, really upper case strings unless you are using Allegro in its incompatible 'modern' mode. The exceptions are the `CL` and `CL-USER` packages which I've given in upper case: this is slightly inconsistent, sorry. Symbol names are always given in lower case, although they too are all upper case of course.

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.0.0
5.0.0
35 changes: 35 additions & 0 deletions impl.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,41 @@ macro."
,@afters
(find-package ',name))))))

(defmacro define-conduit-package (name &body clauses)
"Version of DEFINE-PACKAGE which adds a (:use)
This also checks for explicit (:use x) clauses and signals appropriate
restartable errors.
See DEFINE-PACKAGE"
(let ((effective-clauses
(if (find-if (lambda (clause)
(and (consp clause)
(eql (car clause) ':use)
(not (null (cdr clause)))))
clauses)
(restart-case
(error 'conduit-error ;help RESTART-CASE
:package name
:format-control "Conduit package ~A uses other packages"
:format-arguments (list name))
(continue ()
:report "Blunder on with this likely-bogus conduit"
clauses)
(use-value (ec)
:report "Use other clauses (interactively: remove the offending clauses)"
:interactive (lambda ()
(list (remove-if (lambda (clause)
(and (consp clause)
(eql (car clause) ':use)
(not (null (cdr clause)))))
clauses)))
ec))
clauses)))
`(define-package ,name
(:use)
,@effective-clauses)))

(defmacro defpackage (name &body clauses)
"DEFPACKAGE for conduit packages
Expand Down
1 change: 1 addition & 0 deletions pkg.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
;; Extensible DEFPACKAGE
(:export
#:define-package
#:define-conduit-package
#:*define-package-mechanisms*
#:*extended-cl-define-package-clause-keys*
#:initial-define-package-state
Expand Down

0 comments on commit d5bf983

Please sign in to comment.