anchor.diff: +(in-package :next-hooks)
  +
   (defvar *hook* nil
     "The hook currently being run.")
   
  
positive.code:   (:method ((*hook* symbol) &rest args)
      (loop for fn in (symbol-value *hook*)
              thereis (apply fn args))))
  
negative.code:   (:documentation "Add FN to the value of HOOK.")
    (:method ((hook symbol) fn &key append)
      (declare (type (or function symbol) fn))
      (serapeum:synchronized (hook)
        (if (not append)
            (pushnew fn (symbol-value hook))
            (unless (member fn (symbol-value hook))
              (alexandria:appendf (symbol-value hook) (list fn)))))))
  
  (defgeneric remove-hook (hook fn)
    (:documentation "Remove FN from the symbol value of HOOK.")
    (:method ((hook symbol) fn)
      (serapeum:synchronized (hook)
        (alexandria:removef (symbol-value hook) fn))))
  
  (defmacro with-hook-restart (&body body)
    `(with-simple-restart (continue "Call next function in hook ~s" *hook*)
       ,@body))
  
  (defun run-hooks (&rest hooks)          ; TODO: What about running hooks over arguments?
    "Run all the hooks in HOOKS.
  The variable `*hook*' is bound to the name of each hook as it is being
  run."
  