(module queue mzscheme
(provide empty empty? insert insert* remove first)
(define-struct queue (front back) (make-inspector))
(define empty (make-queue '() '()))
(define (empty? Q)
(and (null? (queue-front Q))
(null? (queue-back Q))))
(define (insert Q x)
(make-queue (queue-front Q)
(cons x (queue-back Q))))
(define (insert* Q elms)
(if (null? elms)
Q
(insert* (insert Q (car elms)) (cdr elms))))
(define (remove Q)
(cond
[(and (null? (queue-front Q)) (null? (queue-back Q)))
(error "remove: The queue is empty")]
[(null? (queue-front Q))
(remove (make-queue (reverse (queue-back Q)) '()))]
[else
(values (car (queue-front Q))
(make-queue (cdr (queue-front Q)) (queue-back Q)))]))
(define (first Q)
(cond
[(empty? Q)
(error "first: The queue is empty")]
[(null? (queue-front Q))
(first (make-queue (reverse (queue-back Q)) '()))]
[else
(car (queue-front Q))]))
)