This site is a static rendering of the Trac instance that was used by R7RS-WG1 for its work on R7RS-small (PDF), which was ratified in 2013. For more information, see Home. For a version of this page that may be more recent, see QueuesCowan in WG2's repo for R7RS-large.

Queues­Cowan

cowan
2014-09-21 08:37:14
11history
source

Abstract

Queues (more precisely, mostly-output-restricted deques) are mutable ordered collections that can contain any Scheme object. Each queue is based on an ordinary Scheme list that contains the elements of the queue by maintaining pointers to the first and last pairs of the list. It's cheap to add or remove elements from the front of the list or to add elements to the back, but not to remove elements from the back. Queues are disjoint from other types of Scheme objects.

Rationale

Because the representation of queues as lists is exposed by the implementation, it's not necessary to provide a comprehensive API for queues, since SRFI 1 and other list APIs can serve the same purpose, using the queue->list, list->queue, and list-queue! procedures to convert between queues and lists fairly cheaply. Consequently, the API provided here over and above the bare necessities of queueing and dequeueing elements is closely analogous to the R7RS-small API for lists. It also subsumes the Chicken and SLIB APIs.

Specification

Constructors

(make-queue k [ fill ])

(queue element ...)

Returns a newly allocated queue containing the elements. This operation is O(n).

(queue-copy queue)

Returns a newly allocated queue containing the elements of queue. This operation is O(n).

(queue-unfold stop? mapper successor seed)

If the result of applying the predicate stop? to seed is #f, return a newly allocated empty queue. Otherwise, apply the procedure mapper to seed. Mapper returns a value which is added to the end of the queue. Then get a new seed by applying the procedure successor to seed, and repeat this algorithm.

(queue-unfold-right stop? mapper successor seed)

If the result of applying the predicate stop? to seed is #f, return a newly allocated empty queue. Otherwise, apply the procedure mapper to seed. Mapper returns a value which is added to the beginning of the queue. Then get a new seed by applying the procedure successor to seed, and repeat this algorithm.

Predicates

(queue? obj)

Returns #t if obj is a queue, and #f otherwise. This operation is O(1).

(queue-empty? queue)

Returns #t if obj is a queue with no elements, and #f otherwise. This operation is O(1).

Accessors

(queue-first queue element)

Returns the first element of the queue. This operation is O(1).

(queue-last queue element)

Returns the last element of the queue. This operation is O(1).

Mutators

These procedures signal an error that satisfies queue-error? if there is no element to delete or modify.

(queue-add-first! queue element)

Adds element to the beginning of queue. Returns an unspecified value. This operation is O(1).

(queue-add-last! queue element)

Adds element to the end of queue. Returns an unspecified value. This operation is O(1).

(queue-remove-first! queue)

Removes the first element of the queue and returns it. This operation is O(1).

(queue-remove-last! queue)

Removes the last element of the queue and returns it. This operation is O(n), because the list does not have backward links.

The whole queue

(queue-length queue)

Returns the number of elements in queue. This operation is O(n).

(queue-append queue ...)

Returns a queue which contains all the elements in all the queues in the order in which they appear in the call. The result does not share storage with any of the arguments. This operation is O(n) in the total number of elements.

Mapping

(queue-map proc queue)

Applies proc to each element of queue in order and returns a newly allocated queue containing the results. This operation is O(n).

(queue-map! proc queue)

Applies proc to each element of queue in order and modifies queue to contain the results. This operation is O(n). It is not part of the R7RS-small list API, but is included here to make transformation of a queue by mutation more efficient.

(queue-for-each proc queue)

Applies proc to each element of queue in order, discarding the returned values. Returns an unspecified value. This operation is O(n).

Conversion and list operations

(queue->list queue)

Returns the list that contains the members of queue in order. It is an error to mutate the cdrs of such a list, as it shares storage with the queue. This operation is O(1).

(list->queue list)

Returns a newly allocated queue containing the elements of list in order. It is an error to mutate the cdrs of list after calling this procedure, as it shares storage with the queue. This operation is O(n).

To apply a non-destructive list procedure to a queue and return a new queue, use (list->queue (proc (queue->list queue))).

(list->queue! queue list)

Replaces the list associated with queue with list, effectively discarding all the elements of queue in favor of those in list. It is an error to mutate the cdrs of list after calling this procedure, as it shares storage with the queue. Returns an unspecified value. This operation is O(n).

To apply a destructive list procedure to a queue, use (list->queue! (proc (queue->list queue))).

Queues as hooks

(queue-invoke queue arg ...)

Apply each element of queue in turn to the args. It is an error if any element is not a procedure. This allows queues to be used as hooks, which various parts of a program can register interest in by adding a procedure to the queue.

Comparator

queue-comparator

A comparator suitable for use with queues, using the procedures of list-comparator.

(make-queue-comparator element-comparator)

Returns a comparator for queues using element-comparator to compare the elements.

Implementation note

R5RS implementations do not have make-list, list-copy, list-set!, or map!, which therefore are packaged with the sample implementation. All but list-set! are available in SRFI 1, but it's trivial to provide local implementations of them.