That would work if the external references you make, are only to those
cons cells, and not to the individual key or value!
More precisely, if you need a WEAK-OR, I would do:
(defstruct wrapper
object
other)
(defun wrap-association (key value)
(let ((key-wrapper (make-wrapper :object key))
(val-wrapper (make-wrapper :object value)))
(setf (wrapper-other key-wrapper) val-wrapper
(wrapper-other val-wrapper) key-wrapper)
(values key-wrapper
val-wrapper)))
(defparameter *table* (make-hash-table #+allegro :weak-key t :values t))
(multiple-value-bind (kw vw) (wrap-association key value)
(setf (gethash kw *table*) vw)
(setf vw nil) ; lost reference to the value wrapper, but we still have a
;; reference to kw -> key -> vw -> value, so nothing's lost.
(setf kw nil) ; lost reference to the key wrapper, we don't have
;; a reference to the value, so kw AND vw can be GC'ed,
;; and the entry can be removed from the HT.
)
We can also use: (setf (gethash (wrapper-object kw) *table*) vw)
as long as we keep a reference to the key wrappers kw.
Note: if multiple such tables are used with keys in common, we have to
use one key wrapper/value wrapper circular list per table, so we need to
keep a list of key wrapper to retain the entries in all the tables.
Everywhere we would have used the key or the value, we would have to use
the wrapper instead.