(defstruct fifo "fifo queue: add to back, pop from front" (max 20) all (front 0) (back 0)) (defun fifo-new (n) (make-fifo :max n :all (make-array `(,n) :initial-element nil))) (defun fifo-push (x e &optional (reaper #'identity)) " The 'all' array is a circular list. when the 'back pointer sweeps around and heads the front' pointer, the 'front' pointer is pushed on one and the doomed item at the old front is passed to a 'reaper' function. And I tried doing this with circular lists but the print got too complicated." (labels ((fifo+ (n e) (if (>= n (1- (fifo-max e))) 0 (+ n 1)))) (let* ((front0 (fifo-front e)) (back0 (fifo-back e)) (front1 (fifo+ front0 e)) (back1 (fifo+ back0 e))) (setf (aref (fifo-all e) back1) x) (setf (fifo-back e) back1) (when (= back1 front0) (setf (fifo-front e) front1) (let ((doomed (aref (fifo-all e) front0))) (when doomed (funcall reaper e doomed)))) x))) (defun test-fifo () (labels ((garbage (e x) (format t "dumping ~a from ~a~%" x e))) (let ((e (fifo-new 10))) (dotimes (i 12 e) (fifo-push (* 10 i) e #'garbage) (when (= i 5) (print e) (terpri)) (when (= i 10) (print e) (terpri))))))