1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- ;; WARNING: This implementation makes use of mutation. It uses the trick of
- ;; storing members in the environment of a returned closure and mutating these
- ;; members inside the closure.
- ;;; Queue obect
- ;; Implemented operations:
- ;; 'push x: push x onto the rear of the queue
- ;; 'pop: remove the head of the queue and return it
- ;; 'peek: return the head of the queue
- ;; 'show: show the queue's contents
- ;; 'fb: show the front and back parts of the queue (for debugging)
- (define make-queue
- ;; make-queue takes no arguments. the queue will be empty initially.
- (lambda ()
- ;; a queue is a procedure
- (let ((front '()) (back '()))
- ;; in this procedure front and back are 2 stacks which are bound in the
- ;; environment. the procedure takes 2 arguments: a desired operation and
- ;; the data on which to work on.
- (lambda (cmd . data)
- ;; ???
- (define exchange
- (lambda ()
- ;; WARNING: mutation here
- (set! front (reverse back))
- (set! back '())))
- (define pop
- (lambda (stack)
- (let ([res (car stack)])
- (set! front (cdr stack))
- res)))
- ;; match on cmd.
- (case cmd
- ;; We push new elements on top of the back stack, because they are
- ;; the ones we want to retrieve last (FIFO - first in first
- ;; out). When the front stack is empty, the back stack will be
- ;; reversed and thus the last pushed element will be the one at the
- ;; bottom of the stack, making it the last one we will pop.
- [(push)
- (set! back (cons (car data) back))]
- [(pop)
- (cond
- [(null? front)
- (exchange)
- (pop front)]
- [else
- (pop front)])]
- ;; If we are trying to access the head of the queue, but there is no
- ;; element stored in the front stack, perform the exchange operation
- ;; and only then return the head of the mutated front stack. If there
- ;; is an element at the head of the front stack in the first place,
- ;; return that instead.
- [(peek)
- (unless (pair? front)
- (exchange))
- (car front)]
- ;; show is displaying the queue's contents
- [(show)
- (display
- (simple-format
- #f "~s\n"
- (append front (reverse back))))]
- ;; fb = front / back
- [(fb)
- (display
- (simple-format
- #f "front: ~s, back: ~s\n"
- front back))]
- ;; Otherwise signal an error.
- [else
- (error "Illegal cmd to queue object" cmd)])))))
|