anchor.diff:  (in-package :serapeum)
   (in-readtable :fare-quasiquote)
   
  +;;; * Functions
   (export '(flip nth-arg
             distinct
             throttle #+ () debounce
  
positive.code: WAIT, of course, may be a fractional number of seconds.
  
  The throttled function is not thread-safe by default; use SYNCHRONIZED
  to get a version with a lock."
    (let* ((fn (ensure-function fn))
           (thunk
             (let ((last 0)
                   (cache '(nil)))
               (lambda (&rest args)
                 (when (<= (- wait (- (get-universal-time) last)) 0)
                   (setf last (get-universal-time)
                         cache (multiple-value-list (apply fn args))))
                 (values-list cache)))))
      (if (not synchronized)
          thunk
          (let ((lock (bt:make-lock)))
            (lambda (&rest args)
              (bt:with-lock-held (lock)
                (apply thunk args)))))))
  
  (defun once (fn)
    "Return a function that runs FN only once, caching the results
  
negative.code:                         (funcall key arg))
                    t)))))
  
  (defun throttle (fn wait &key synchronized memoized)
    "Wrap FN so it can be called no more than every WAIT seconds.
  If FN was called less than WAIT seconds ago, return the values from the
  last call. Otherwise, call FN normally and update the cached values.
  