I'd say that extending the reader is better not handled by "#."
The whole point of my proposal to add #. to Scheme is precisely to extend the reader at read time. Secondary purposes include folding a constant expression that the compiler is not able to fold by itself, and expanding a #. form into a lambda-list, record clause, cond clause, or other non-expression.
Here's a simplified description of how CL `read` operates. When a character is read, it is looked up in the current readtable (which is bound to the dynamic variable *readtable*), which maps each Unicode character into one of six lexical syntax types: an invalid character, a whitespace character, a constituent character, a single escape character, a multiple escape character, or a macro character.
In the main `read` loop: An invalid character raises an exception; a whitespace character is ignored. Single and multiple escapes behave like \ and | respectively. A sequence of constituent characters (including escaped characters) are assembled into a token; when a non-constituent character is seen, the token is complete, and it is examined to see if it is an identifier or number, which is returned as the value of `read`. If the token is neither, an exception is raised.
Finally, if a macro character is read, the associated read macro is invoked. If it returns one value, that is returned as the value of `read`. If it returns no values, `read` examines the next character as explained above. Dispatching macro characters like # have their own sub-readtable; digits are accumulated and passed as an integer to any read macro associated with the first non-digit character.
Finally, the initial macro characters are:
left paren, which uses read-delimited-list;
single quote, which recursively calls read;
semicolon, which returns zero values;
backquote, like quote (but in CL the expression returned is implementation-dependent rather than a macro call, which is safe because built-in identifiers cannot be rebound);
comma, which peeks for an @ and then calls read recursively;
hash sign, which dispatches using a sub-readtable (for hysterical raisins, # is allowed inside identifiers). The initial hash sign sequences are #., #: (uninterned symbol), #b, #o, #x, #r (arbitrary radix from 2 to 36), #c (2-element lists to complex numbers), #a (arrays of specified rank), #s (list of structure type followed by name and value), #p (pathname objects), #=, ##, #+ (ifdef, returns zero or one value), #- (ifndef, returns zero or one value), #| (returns zero values). Everything else raises an exception.
John Cowan
http://vrici.lojban.org/~cowan xxxxxx@ccil.org"Repeat this until 'update-mounts -v' shows no updates.
You may well have to log in to particular machines, hunt down
people who still have processes running, and kill them."