circular arrays


Write a circular buffer data structure.

 $ cat cirbuf.rkt 
 #lang racket 
  
 (define (circular-buffer n) 
  
   (let 
  
     ((elements (make-vector n)) 
      (head 0) 
      (tail 0) 
      (count 0)) 
  
     (lambda (cmd . args) 
       (case (list 'quote cmd) 
  
         (('mt) 
            (= count 0)) 
   
         (('dq) 
            (if (= count 0) 
              (raise-user-error 
                'circular-buffer "calling dequeue on an empty queue") 
              (let ((e (vector-ref elements head))) 
                (set! count (- count 1)) 
                (set! head (remainder (+ head 1) n)) 
                e))) 
  
         (('nq) 
            (if (= count n) 
              (raise-user-error 
                'circular-buffer "calling enqueue on a full queue") 
              (begin 
                (vector-set! elements tail (car args)) 
                (set! count (+ count 1)) 
                (set! tail (remainder (+ tail 1) n))))) 
  
         (else 
           (raise-user-error 
             'circular-buffer "Don't recognize ~a as a command" cmd)))))) 
  
  
 (require rackunit "utl.rkt") 
  
 (let* ((n 10) 
        (l (permuted-iota n)) 
        (cb (circular-buffer n))) 
  
   (let loop ((l l)) 
     (unless (null? l) 
       (cb 'nq (car l)) 
       (loop (cdr l)))) 
    
   (check-eq? (cb 'mt) #f) 
    
   (let loop ((l l)) 
     (unless (null? l) 
       (check-eq? (cb 'dq) (car l)) 
       (loop (cdr l)))) 
  
   (check-eq? (cb 'mt) #t)) 
  
  
 $ racket cirbuf.rkt 
  
 $