Turn contracts on enqueue!' and
dequeue!' into the usual error checks.
On a simple benchmark of: (let ([N 100000] [M 20] [q (make-queue)]) (time (for ([i (in-range M)]) (for ([i (in-range (* i N))]) (enqueue! q i)) (unless (for/and ([i (in-range (* i N))]) (list i (dequeue! q))) (error "poof"))))) I get these timings: original version: cpu time: 24438 real time: 24439 gc time: 8164 single-links: cpu time: 17848 real time: 17849 gc time: 4859 this version: cpu time: 6519 real time: 6519 gc time: 3032 In addition, cleaned up the documentation a little, and mention the fact that it is not thread safe.
This commit is contained in:
parent
d986fed725
commit
3f36d054f6
|
@ -36,18 +36,16 @@
|
|||
(check-true (queue-empty? q)))))
|
||||
(test-suite "dequeue!"
|
||||
(test-case "make-queue"
|
||||
(check-exn exn:fail:contract? (lambda () (dequeue! (make-queue)))))
|
||||
(check-exn exn:fail? (lambda () (dequeue! (make-queue)))))
|
||||
(test-case "enqueue! once"
|
||||
(let* ([q (make-queue)])
|
||||
(enqueue! q 1)
|
||||
(check-equal? (dequeue! q) 1)
|
||||
(check-exn exn:fail:contract?
|
||||
(lambda () (dequeue! q)))))
|
||||
(check-exn exn:fail? (lambda () (dequeue! q)))))
|
||||
(test-case "enqueue! twice"
|
||||
(let* ([q (make-queue)])
|
||||
(enqueue! q 1)
|
||||
(enqueue! q 2)
|
||||
(check-equal? (dequeue! q) 1)
|
||||
(check-equal? (dequeue! q) 2)
|
||||
(check-exn exn:fail:contract?
|
||||
(lambda () (dequeue! q))))))))
|
||||
(check-exn exn:fail? (lambda () (dequeue! q))))))))
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
(define (nonempty-queue? v) (and (queue? v) (queue-head v) #t))
|
||||
|
||||
(define (enqueue! q v)
|
||||
(unless (queue? q) (raise-type-error enqueue! "queue" 0 q))
|
||||
(let ([new (link v #f)])
|
||||
(if (queue-head q)
|
||||
(set-link-tail! (queue-tail q) new)
|
||||
|
@ -24,7 +25,9 @@
|
|||
(set-queue-tail! q new)))
|
||||
|
||||
(define (dequeue! q)
|
||||
(unless (queue? q) (raise-type-error dequeue! "queue" 0 q))
|
||||
(let ([old (queue-head q)])
|
||||
(unless old (error 'dequeue! "empty queue"))
|
||||
(set-queue-head! q (link-tail old))
|
||||
(link-value old)))
|
||||
|
||||
|
@ -38,11 +41,13 @@
|
|||
(define nonempty-queue/c
|
||||
(flat-named-contract "nonempty-queue" nonempty-queue?))
|
||||
|
||||
;; ELI: Are these needed? (vs just providing `queue?', `make-queue' and
|
||||
;; `queue-empty?'.)
|
||||
(provide/contract
|
||||
[queue/c flat-contract?]
|
||||
[nonempty-queue/c flat-contract?]
|
||||
[queue? (-> any/c boolean?)]
|
||||
[make-queue (-> queue/c)]
|
||||
[queue-empty? (-> queue/c boolean?)]
|
||||
[enqueue! (-> queue/c any/c void?)]
|
||||
[dequeue! (-> nonempty-queue/c any/c)])
|
||||
[queue-empty? (-> queue/c boolean?)])
|
||||
|
||||
(provide enqueue! dequeue!)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#lang scribble/manual
|
||||
@(require scribble/eval "utils.rkt" (for-label racket unstable/queue))
|
||||
@(define qeval (eval/require 'unstable/queue))
|
||||
|
||||
@title{Imperative Queues}
|
||||
|
||||
|
@ -7,59 +8,56 @@
|
|||
|
||||
@unstable[@author+email["Carl Eastlund" "cce@racket-lang.org"]]
|
||||
|
||||
This module provides a mutable queue representation.
|
||||
This module provides a simple mutable queue representation,
|
||||
first-in/first-out only. Operations on queues mutate it in a
|
||||
thread-unsafe way.
|
||||
|
||||
@defproc[(make-queue) queue/c]{
|
||||
Produces an empty queue.
|
||||
Produces an empty queue.
|
||||
}
|
||||
|
||||
@defproc[(enqueue! [q queue/c] [v any/c]) void?]{
|
||||
Adds an element to the back of a queue.
|
||||
Adds an element to the back of a queue.
|
||||
}
|
||||
|
||||
@defproc[(dequeue! [q nonempty-queue/c]) any/c]{
|
||||
Removes an element from the front of a nonempty queue, and returns that element.
|
||||
Removes an element from the front of a nonempty queue, and returns that
|
||||
element.
|
||||
|
||||
@defexamples[
|
||||
#:eval (eval/require 'unstable/queue)
|
||||
(define q (make-queue))
|
||||
(enqueue! q 1)
|
||||
(dequeue! q)
|
||||
(enqueue! q 2)
|
||||
(enqueue! q 3)
|
||||
(dequeue! q)
|
||||
(dequeue! q)
|
||||
]
|
||||
@defexamples[#:eval qeval
|
||||
(define q (make-queue))
|
||||
(enqueue! q 1)
|
||||
(dequeue! q)
|
||||
(enqueue! q 2)
|
||||
(enqueue! q 3)
|
||||
(dequeue! q)
|
||||
(dequeue! q)]
|
||||
}
|
||||
|
||||
@defproc[(queue-empty? [q queue/c]) boolean?]{
|
||||
Recognizes whether a queue is empty or not.
|
||||
Recognizes whether a queue is empty or not.
|
||||
|
||||
@defexamples[
|
||||
#:eval (eval/require 'unstable/queue)
|
||||
(define q (make-queue))
|
||||
(queue-empty? q)
|
||||
(enqueue! q 1)
|
||||
(queue-empty? q)
|
||||
(dequeue! q)
|
||||
(queue-empty? q)
|
||||
]
|
||||
@defexamples[#:eval qeval
|
||||
(define q (make-queue))
|
||||
(queue-empty? q)
|
||||
(enqueue! q 1)
|
||||
(queue-empty? q)
|
||||
(dequeue! q)
|
||||
(queue-empty? q)]
|
||||
}
|
||||
|
||||
@defproc[(queue? [v any/c]) boolean?]{
|
||||
This predicate recognizes queues.
|
||||
This predicate recognizes queues.
|
||||
|
||||
@defexamples[
|
||||
#:eval (eval/require 'unstable/queue)
|
||||
(queue? (make-queue))
|
||||
(queue? 'not-a-queue)
|
||||
]
|
||||
@defexamples[#:eval qeval
|
||||
(queue? (make-queue))
|
||||
(queue? 'not-a-queue)]
|
||||
}
|
||||
|
||||
@deftogether[(
|
||||
@defthing[queue/c flat-contract?]
|
||||
@defthing[nonempty-queue/c flat-contract?]
|
||||
@defthing[queue/c flat-contract?]
|
||||
@defthing[nonempty-queue/c flat-contract?]
|
||||
)]{
|
||||
These contracts recognize queues; the latter requires the queue to contain at
|
||||
least one value.
|
||||
These contracts recognize queues; the latter requires the queue to
|
||||
contain at least one value.
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user