On Wed, Mar 24, 2004 at 07:30:03PM +0200, Nikodemus Siivola wrote:
> I've been working on package locks for SBCL recently, and things are going
> pretty smoothly. Before I get too entrenched, however, I wanted to ask for
> general comments on the protocol (attached) and specifically about
> Methods are not mentioned in the attached document, but I see essentially
> two ways to go:
> * Provide similar guarantees to methods in locked packages
> as ANSI provides for methods in the COMMON-LISP package.
> - Easy to conseptualize due to similarity to CL.
> - Allows users of the package to extend the methods
> without accidentally intruding on the internal assumptions.
> - Methods don't conseptually belong in packages but
> to generic functions. Locking for methods should
> be provided by a CLOS extension instead.
> - Packages that expect users to add methods specializing
> on classes visible in the locked package need to
> go through some contortion so allow this if they wish to
> use package locking -- eg. defining those methods in
> another package and re-exporting them.
> * Don't extend package locking to methods.
> - Clean and nice, doesn't violate conseptual barriers.
> - If a package exports names of generic functions it
> cannot rely on having the method it expcts to be dispatched.
> This means that sometimes packages will have to go through some
> contortions to separate external and internal interfaces.
> I don't have any deep convictions either way, so comments would be more
> than welcome on this -- and the proposal in general.
My inclination is not to extend package locking to methods. The
protections that ANSI CL provides for methods in the CL package don't
seem to me like a locked-package feature of #<PACKAGE "COMMON-LISP">,
but a locked-GENERIC-FUNCTION feature of all predefined generic
functions. Thus, I think that if they're to be extended to user-defined
generic functions, locking GENERIC-FUNCTIONs would be the way to go.
> * Package Locks
> Package locks protect against unintentional modifications of a
> package: they provide similar protection to user packages as is
> mandated to COMMON-LISP package by the ANSI.
> ** Implementation Packages
> Each package has a list of associated implementation packages, within
> which the package can be modified despite possible package lock.
Does "within which" here mean that the locked package can be modified
if and only if *PACKAGE* is bound to one of the associated
> Unless explicitly altered by CL:DEFPACKAGE,
> ADD-IMPLEMENTATION-PACKAGE, or REMOVE-IMPLEMENTATION-PACKAGE each
> package is its own (only) implementation package.
When I first read this I wondered
x Do you mean that packages default to being locked? Or that after you
x explicitly choose to lock a package (with, e.g., a &KEY argument to
x MAKE-PACKAGE or DEFPACKAGE, or a LOCK-PACKAGE operation) then this
x default (that each package is its own only implementation package)
x comes into effect?
but reading through to the end I see the :LOCK argument on DEFPACKAGE.
Perhaps the text above should be something like
Each package has a list of associated implementation packages. If
a package is locked, then that package, and the symbols which have
that package as their SYMBOL-PACKAGE, can only be modified when
when *PACKAGE* is bound to one of the implementation packages.
> -- Binding it as a catch tag or a restart name.
I wonder about the runtime overhead of this one. Also, is this
something that ANSI provides for its locked packages -- not being able
to CATCH 'ERROR, e.g.? (I spent a few minutes looking for the relevant
section of the Hyperspec, then decided just to mail this question
> macro CL:DEFPACKAGE name [[option]]* => package
> Options are extended to include the following:
> :LOCK boolean
> If the argument to :LOCK is T, the package is initially locked.
> If :LOCK is not provided it defaults to NIL.
> :IMPLEMENT package-designator*
> The package is added as an implementation package to the packages
> named. If :IMPLEMENT is not provided, it defaults to the package
> (defpackage "FOO" (:export "BAR") (:lock t) (:implement))
> (defpackage "FOO-INT" (:use "FOO") (:implement "FOO" "FOO-INT"))
> ;;; is equivalent to
> (defpackage "FOO") (:export "BAR"))
> (lock-package "FOO")
> (remove-implementation-package "FOO" "FOO")
> (defpackage "FOO-INT" (:use "BAR"))
> (add-implementation-package "FOO-INT" "FOO")
This question probably shows my heritage of C++ dain-bramage, but...
might FRIEND instead of IMPLEMENTATION, as in
+ (defpackage "FOO" (:export "BAR") (:lock t) (:friends))
+ (defpackage "FOO-INT" (:use "FOO") (:implement "FOO" "FOO-INT"))
+ ;;; is equivalent to
+ (defpackage "FOO") (:export "BAR"))
+ (lock-package "FOO")
+ (remove-friend-packages "FOO" "FOO")
+ (defpackage "FOO-INT" (:use "BAR"))
+ (add-friend-packages "FOO-INT" "FOO")
(and in documentation text) be more mnemonic? (And I don't know, maybe
the term IMPLEMENTATION conforms to some other package-locking
implementation and you don't want to be gratuitously inconsistent.)
William Harold Newman <william.newman@...>
Public choice model, 1; public interest model, 0.
PGP key fingerprint 85 CE 1C BA 79 8D 51 8C B9 25 FB EE E0 C3 E5 7C