diff --git a/collects/data/queue.rkt b/collects/data/queue.rkt index 6c733178d1..cec99343e9 100644 --- a/collects/data/queue.rkt +++ b/collects/data/queue.rkt @@ -1,6 +1,6 @@ #lang racket/base -;; A Queue contains a linked list with mutable cdrs, hoding two pointers +;; A Queue contains a linked list with mutable cdrs, holding two pointers ;; to the head and the tail -- where items are pulled from the head and ;; pushed on the tail. It is not thread safe: mutating a queue from ;; different threads can break it. @@ -31,6 +31,13 @@ (set-queue-head! q (link-tail old)) (link-value old))) +(define (queue-count queue) + (let loop ([link (queue-head queue)] + [count 0]) + (if (not link) + count + (loop (link-tail link) (add1 count))))) + ;; --- contracts --- (require racket/contract) @@ -48,6 +55,7 @@ [nonempty-queue/c flat-contract?] [queue? (-> any/c boolean?)] [make-queue (-> queue/c)] - [queue-empty? (-> queue/c boolean?)]) + [queue-empty? (-> queue/c boolean?)] + [queue-count (-> queue/c integer?)]) (provide enqueue! dequeue!) diff --git a/collects/data/scribblings/queue.scrbl b/collects/data/scribblings/queue.scrbl index b6f8ecd850..2849090fbf 100644 --- a/collects/data/scribblings/queue.scrbl +++ b/collects/data/scribblings/queue.scrbl @@ -34,6 +34,19 @@ thread-unsafe way. (dequeue! q)] } +@defproc[(queue-count [queue queue/c]) integer?]{ + Returns the number of elements in the queue. + + @defexamples[#:eval qeval + (define queue (make-queue)) + (queue-count queue) + (enqueue! queue 5) + (enqueue! queue 12) + (queue-count queue) + (dequeue! queue) + (queue-count queue)] +} + @defproc[(queue-empty? [q queue/c]) boolean?]{ Recognizes whether a queue is empty or not. diff --git a/collects/tests/data/queue.rkt b/collects/tests/data/queue.rkt index 1174f1fef2..1b8eeb318e 100644 --- a/collects/tests/data/queue.rkt +++ b/collects/tests/data/queue.rkt @@ -34,6 +34,21 @@ (dequeue! q) (dequeue! q) (check-true (queue-empty? q))))) + (test-suite "count" + (test-case "count empty" + (let* ([queue (make-queue)]) + (check-equal? (queue-count queue) 0))) + (test-case "count enqueue once" + (let* ([queue (make-queue)]) + (enqueue! queue 5) + (check-equal? (queue-count queue) 1))) + (test-case "count enqueue thrice dequeue once" + (let* ([queue (make-queue)]) + (enqueue! queue 5) + (enqueue! queue 9) + (enqueue! queue 12) + (dequeue! queue) + (check-equal? (queue-count queue) 2)))) (test-suite "dequeue!" (test-case "make-queue" (check-exn exn:fail? (lambda () (dequeue! (make-queue)))))