[cdr-discuss] [RfC] WITH-READTABLE-ITERATOR
Tobias C. Rittweiler
tcr at freebits.de
Thu Oct 2 20:07:32 UTC 2008
Request for comments. Including grammatical and stylistic corrections.
Forum: Common Lisp Document Repository (CDR)
* CLHS 2.1.1 Readtables
* X3J13 Issue #188
* `with-package-iterator' (macro)
* `with-hash-table-iterator' (macro)
Edit History: 02-Oct-2008 by Rittweiler (Draft)
Even though the ANSI Common Lisp standard provides simple getters for
readtables (`get-macro-character', `get-dispatch-macro-character'), the
standard does not provide any means to efficiently get at all the macro
characters and dispatch macro characters defined in a readtable.
The omission of any iteration facility for readtables makes readtables
unneccessarily opaque, and keep users from writing libraries that try to deal
with readtables in a general way. For example, the author discovered that this
lack of an iteration form is the main obstacle to writing an otherwise
portable library that establishes an organizational namespace for readtables
akin to the namespace that is provided for packages.
Add a macro `with-readtable-iterator' that establishes a generator in its
scope; each invocation of this generator returns a macro character or a
dispatch macro character from the readtable the generator was established
for--along side some additional information.
A detailed specification of `with-readtable-iterator' can be found in the
appendix of this document.
The proposed macro `with-readtable-iterator' represents a general iteration
facility for readtables that can be used to implement a variety of iteration
The proposal is closely modelled on the macros `with-hash-table-iterator' and
`with-package-iterator'. The semantics of `with-readtable-iterator' should
thus be intuitive to any experienced Common Lisp programmer.
The proposal does deliberately say nothing about the home-package of the
symbol `with-readtable-iterator'. However, implementors are encouraged to
export this symbol from their extensions package (often called "`EXT'") or
another appropriate package--unless a later CDR document specifies a more
No implementation the author is aware of provides a way to iterate through a
The author implemented the proposal for SBCL (http://www.sbcl.org/), and sent
the relevant patches upstream; the patches are currently waiting to be
integrated into mainline. Ariel Badichi implemented the proposal for CLISP
(http://clisp.cons.org/), and is going to send his work upstream shortly.
Stephen Compall did an implementation for Clozure CL (http://ccl.clozure.com/)
which needs to be somewhat revised to fully conform to the proposal as
presented in this document.
Cost to implementators
The macro `with-readtable-iterator' should be straightforwardly
implementable. Extrapolating from actual experience, people--who were
previously not acquainted with the relevant code sections--were able to
implement it in a couple of hours.
Ariel Badichi proposed coalescing a generator's fourth return value
(indicating if the returned character is a dispatch macro character) with its
first return value (indicating if the generator is exhausted.)
There is technically no reason that speaks against doing so; in fact, a
generator would return one value less this way--which may lead to positive
performance characteristics on register-anemic processor architectures.
Stephen Compall and the author opposed such a change mostly for idiomatic
reasons, as both `with-hash-table-iterator' and `with-package-iterator', the
generator-establishing macros specified by the ANSI standard, return a purely
boolean exhaustion flag as first value. In particular, `with-package-iterator'
does _not_ coalesce the accessibility type (third return value) with the
exhaustion flag (first return value.)
The author notes that allowing `:terminating', and `:non-terminating' as valid
MACRO-CHAR-TYPES was considered, but rejected for reasons of simplicity. It is
not apparent that there is a real necessity for supporting these out of the
The author wants to specially credit Ariel Badichi and Stephen Compall which
in spirit of true hackerism promptly agreed to hack an early version of the
proposal into the implementations of their choice.
-- Macro: with-readtable-iterator
(name readtable &rest macro-char-types) declaration* form*
Arguments and Values
NAME - A symbol.
READTABLE - A form, evaluated once to produce a readtable.
MACRO-CHAR-TYPE - One of the symbols `:macro-char', or `:dispatch-macro-char'.
DECLARATION - A `declare' expression; not evaluated.
FORMS - An implicit progn.
RESULTS - The values of the FORMS.
Within the lexical scope of the body FORMS, the NAME is defined via `macrolet'
such that successive invocations of `(name)' will return the macro characters,
one by one, from the READTABLE. The order of the macro characters returned is
An invocation of `(name)' returns the following five values:
1. A generalized boolean that is true if a macro character is returned.
2. A macro character that is defined in READTABLE.
3. A reader macro function of the macro character returned.
4. A generalized boolean that is true if the macro character is a dispatch
5. An association list between the "sub-characters" of the dispatch macro
character and their reader macro functions.
After all macro characters have been returned by successive invocations of
`(name)', only one value is returned, namely `nil'.
It is unspecified what happens if any of the implicit interior state of an
iteration is returned outside the dynamic extent of the
`with-readtable-iterator' form such as by returning some closure over the
In spirit of CLHS 3.6, consequences are undefined if READTABLE is modified
except for modification of the current macro character under traversal.
Signals an error of type `program-error' if a MACRO-CHAR-TYPE is supplied that
is not recognized by the implementation.
Traversal Rules and Side Effects (CLHS 3.6), `with-package-iterator'
More information about the cdr-discuss