Kaz Kylheku <kkylheku@gmail.com> wrote:
+---------------
| Didier Verna <didier@lrde.epita.fr> wrote:
| > I have a package which is ASDF installable and in which I'd like to use
| > a personal dispatch macro character. This particular DMC should be
| > active when the package files are compiled or evaluated (via ASDF, but
| > ideally in other situations), but I don't want to pollute the rest of
| > the lisp session with it.
...
| Note that the functions COMPILE-FILE and LOAD save and restore the
| values of *PACKAGE* and *READ-TABLE*.
+---------------
Ummm, yes, saves/restores [binds, actually] the values of those
*variables*, but *doesn't* save/restore the objects they contain!!
(See below...)
+---------------
| This is why you can have (IN-PACKAGE "MY-PACKAGE") in a file
| without worrying that loading the file will change the current package.
+---------------
True, but IN-PACKAGE effectively just sets CL:*PACKAGE*, it doesn't mess
with the package *itself* which was the former value of CL:*PACKAGE*.
+---------------
| You can take the same liberty in changing the read table near
| the top of your source files.
+---------------
CAREFUL!! You may safely change the CL:*READTABLE* *variable* here,
but *NOT* the readtable it contains!!!
+---------------
| I would do it via read-time evaluation, since the read table
| adjustment is not useful for load time:
|
| ;; top of the file
| ;; ...
| (in-package :my-package)
| ;; at read time, hash dot!
| #.(set-dispatch-macro-character ...)
| ;; ...
| ;; bottom of file: package and readtable are restored for us!
+---------------
No, the CL:*PACKAGE* and CL:*READTABLE* *variables* are restored
for us, but the objects they originally contained *aren't*!
CL:*PACKAGE* isn't a problem, since you didn't change the formerly-
referenced package object, but by doing the SET-DISPATCH-MACRO-CHARACTER
you *did* mutate the actual readtable that the CL:*READTABLE* previously
held... and now still currently holds, even after the return to the
compiler/loader! (Oops.)
Thomas Burdick already noted up-thread the right way to do this, but
here's the short-short version [steps #2 & #3 may safely be swapped]:
1. Create a *new* readtable object;
2. Make your mods to *that* readtable; and then
3. Assign that object to the CL:*READTABLE* variable.
So, modifying your template:
;; top of the file
;; ...
(in-package :my-package)
(eval-when (:compile-toplevel :load-toplevel :execute)
(setf cl:*readtable*
(let ((my-rt ((copy-readtable rt))))
(flet ((my-func (stream sub-char infix-count)
;; Only if you really do ignore them
(declare (ignore sub-char infix-count))
...{your new syntax implemented here}...))
;; Using "#$" as an example
(set-dispatch-macro-character #\# #\$ my-func my-rt))
my-rt)))
;; New syntax now enabled for the rest of the file.
;; ...
;; bottom of file: package and readtable are restored for us!
The above over-simplified template is really only useful if you have
only *one* file that needs to use the modified syntax and you want
it enabled *everywhere* within that file. Thomas Burdick's version is
better if you need multiple files to use the syntax and/or if you want
to be able to easily turn the syntax on & off within a given file.
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607