From: ············@gmail.com
Subject: set/get-dispatch-macro-character
Date: 
Message-ID: <1106832490.617741.106030@f14g2000cwb.googlegroups.com>
Hi,

I redefine #\ while reading a package:

#.(set-dispatch-macro-character #\# #\\
(lambda (inp c1 c2)
(declare (ignore c1 c2))
(let ((c (peek-char nil inp)))
(cond
((alpha-char-p c)
(ecase (read inp)
(Lpar #\()
(Rpar #\))
(Lsqr #\[)
(Rsqr #\])
(Lcur #\{)
(Rcur #\})
(Lang #\<)
(Rang #\>)
(Tab #\Tab)
(Space #\Space)
(Newline #\Newline)))
(t
(read-char inp))))))


Then, I define functions in the package, and at the end want to restore
the reader:

#.(set-dispatch-macro-character #\# #\\
(get-dispatch-macro-character #\# #\\ (copy-readtable nil)))

CLISP and OpenMCL are happy with it. LispWorks complains:

Error: The variable SYSTEM::SHARP-BACKSLASH is unbound.
1 (continue) Try evaluating SYSTEM::SHARP-BACKSLASH again.
2 Specify a value to use this time instead of evaluating
SYSTEM::SHARP-BACKSLASH.
3 Specify a value to set SYSTEM::SHARP-BACKSLASH to.
4 Return the result of calling (SYSTEM::SHARP-BACKSLASH) instead.

1. Is it a bug in lispworks?
2. Do I understand correctly that I cannot use setq in #.?

From: Edi Weitz
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <uis5j56wr.fsf@agharta.de>
On 27 Jan 2005 05:28:10 -0800, ·············@gmail.com" <············@gmail.com> wrote:

> I redefine #\ while reading a package:
>
> #.(set-dispatch-macro-character #\# #\\
> (lambda (inp c1 c2)
> (declare (ignore c1 c2))
> (let ((c (peek-char nil inp)))
> (cond
> ((alpha-char-p c)
> (ecase (read inp)
> (Lpar #\()
> (Rpar #\))
> (Lsqr #\[)
> (Rsqr #\])
> (Lcur #\{)
> (Rcur #\})
> (Lang #\<)
> (Rang #\>)
> (Tab #\Tab)
> (Space #\Space)
> (Newline #\Newline)))
> (t
> (read-char inp))))))
>
>
> Then, I define functions in the package, and at the end want to restore
> the reader:
>
> #.(set-dispatch-macro-character #\# #\\
> (get-dispatch-macro-character #\# #\\ (copy-readtable nil)))
>
> CLISP and OpenMCL are happy with it. LispWorks complains:
>
> Error: The variable SYSTEM::SHARP-BACKSLASH is unbound.
> 1 (continue) Try evaluating SYSTEM::SHARP-BACKSLASH again.
> 2 Specify a value to use this time instead of evaluating
> SYSTEM::SHARP-BACKSLASH.
> 3 Specify a value to set SYSTEM::SHARP-BACKSLASH to.
> 4 Return the result of calling (SYSTEM::SHARP-BACKSLASH) instead.
>
> 1. Is it a bug in lispworks?

Works for me with LWW 4.4 - which version are you using?

> 2. Do I understand correctly that I cannot use setq in #.?

I don't understand this question.

  CL-USER 7 > (defparameter *a* 0)
  *A*

  CL-USER 8 > #.(setq *a* 42)
  42

  CL-USER 9 > *a*
  42

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: ············@gmail.com
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <1106833860.829249.133020@z14g2000cwz.googlegroups.com>
>
> Works for me with LWW 4.4 - which version are you using?
>

4.3, I think. The last time I looked there was no free 4.4, and I want
to make sure it compiles my code
before I spend money.

> I don't understand this question.
>
>   CL-USER 7 > (defparameter *a* 0)
>   *A*
>
>   CL-USER 8 > #.(setq *a* 42)
>   42
>
>   CL-USER 9 > *a*
>   42

The first naïve attempt has been to .#(setq *readtable*
(copy-readtable nil)) at the bottom of the source file. It left the
readtable with redefined entry for #\.

David
From: Edi Weitz
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <uacqv55t6.fsf@agharta.de>
On 27 Jan 2005 05:51:00 -0800, ·············@gmail.com" <············@gmail.com> wrote:

> The first na�ve attempt has been to .#(setq *readtable*
> (copy-readtable nil)) at the bottom of the source file. It left the
> readtable with redefined entry for #\.

COMPILE-FILE and LOAD bind *READTABLE* and *PACKAGE* to the values
they held before processing the file,[1] that's why your statement
from above didn't have any effect.

You should put 

  .#(setq *readtable* (copy-readtable nil))

at the /beginning/ of your file so you can be sure modifications of
the readtable will only affect this single file.

Cheers,
Edi.

[1] I.e. it is as if you had issued

      (let ((*readtable* *readtable*))
        (load "foo.lisp"))

    instead of just

      (load "foo.lisp").

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: ············@gmail.com
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <1106848345.762997.218260@z14g2000cwz.googlegroups.com>
>   .#(setq *readtable* (copy-readtable nil))
>

CMUCL and CLISP don't digest this:

#.(setq *readtable* (copy-readtable))
Structures of type READTABLE cannot be dumped as constants.

David
From: Edi Weitz
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <uvf9ilpi5.fsf@agharta.de>
On 27 Jan 2005 09:52:25 -0800, ·············@gmail.com" <············@gmail.com> wrote:

>>   .#(setq *readtable* (copy-readtable nil))
>
> CMUCL and CLISP don't digest this:
>
> #.(setq *readtable* (copy-readtable))
> Structures of type READTABLE cannot be dumped as constants.

Try

  .#(progn (setq *readtable* (copy-readtable nil)) nil)

instead.  The compiler tries to dump the return value of the form
while you're only interested in the side effect.  But basically that's
why Pascal recommended to use EVAL-WHEN.  I used this just to
illustrate how to make sure your modifications are limited to one
file.

Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: ············@gmail.com
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <1106849656.367734.21970@f14g2000cwb.googlegroups.com>
> > #.(setq *readtable* (copy-readtable))
> > Structures of type READTABLE cannot be dumped as constants.
>
> Try
>
>   .#(progn (setq *readtable* (copy-readtable nil)) nil)
>
> instead.

I tried before posting the original comment; but forgot that CMUCL does
not recompile automatically, and loads the compiled version instead.
Thanks.

> The compiler tries to dump the return value of the form
> while you're only interested in the side effect.  But basically
that's
> why Pascal recommended to use EVAL-WHEN.  I used this just to
Does not work in CMUCL.
From: ············@gmail.com
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <1106845499.391932.51030@f14g2000cwb.googlegroups.com>
#.(setq *readtable* (copy-readtable))

is what I want, but both clisp and cmucl refuse to compile it saying
that *readtable* cannot be dumped as constant.

David
From: Pascal Costanza
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <ctavgp$a0m$1@snic.vub.ac.be>
············@gmail.com wrote:

> Then, I define functions in the package, and at the end want to restore
> the reader:
> 
> #.(set-dispatch-macro-character #\# #\\
> (get-dispatch-macro-character #\# #\\ (copy-readtable nil)))

I think it's better to install a new macro character like this:

(eval-when (:compile-toplevel :load-toplevel :execute)
   (set-dispatch-macro-character ...))

You don't need to restore the reader, this is ensured by Common Lisp. 
See the issue IN-SYNTAX and the specs for COMPILE-FILE and LOAD in the 
HyperSpec.


Pascal
From: Damien Kick
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <pszq1uhy.fsf@email.mot.com>
Pascal Costanza <··@p-cos.net> writes:

> ············@gmail.com wrote:
> 
> > Then, I define functions in the package, and at the end want to restore
> > the reader:
> > #.(set-dispatch-macro-character #\# #\\
> 
> > (get-dispatch-macro-character #\# #\\ (copy-readtable nil)))
> 
> I think it's better to install a new macro character like this:
> 
> (eval-when (:compile-toplevel :load-toplevel :execute)
>    (set-dispatch-macro-character ...))
> 
> You don't need to restore the reader, this is ensured by Common
> Lisp. See the issue IN-SYNTAX and the specs for COMPILE-FILE and
> LOAD in the HyperSpec.

Thank you very much for pointing out these sections.  The concern I
had in a different thread in which I was wondering if it was bad style
to modify the syntax of #\! for use as a dispatching macro character
seems to be obviated by this technique.
From: Edi Weitz
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <ur7k64zux.fsf@agharta.de>
On Thu, 27 Jan 2005 15:57:31 +0100, Pascal Costanza <··@p-cos.net> wrote:

> You don't need to restore the reader, this is ensured by Common
> Lisp. See the issue IN-SYNTAX and the specs for COMPILE-FILE and
> LOAD in the HyperSpec.

Sure you need to.  Or you need to make sure to work on a copy of the
current readtable.  The special variable is rebound but the object it
is bound to is still the same.

Try to LOAD a file that contains just the line

  (set-macro-character #\# (get-macro-character #\;))

and afterwards try to enter a character in the REPL.  See?

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Pascal Costanza
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <ctb5hj$cg8$1@snic.vub.ac.be>
Edi Weitz wrote:
> On Thu, 27 Jan 2005 15:57:31 +0100, Pascal Costanza <··@p-cos.net> wrote:
> 
>>You don't need to restore the reader, this is ensured by Common
>>Lisp. See the issue IN-SYNTAX and the specs for COMPILE-FILE and
>>LOAD in the HyperSpec.
> 
> Sure you need to.  Or you need to make sure to work on a copy of the
> current readtable.  The special variable is rebound but the object it
> is bound to is still the same.
> 
> Try to LOAD a file that contains just the line
> 
>   (set-macro-character #\# (get-macro-character #\;))
> 
> and afterwards try to enter a character in the REPL.  See?

Oops, you're right. So it should be something like:

(eval-when (:compile-toplevel :load-toplevel :execute)
   (setq *readtable* *my-fancy-readtable*))


...just like it says in the IN-SYNTAX issue writeup...



Pascal
From: ············@gmail.com
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <1106848023.864853.194830@z14g2000cwz.googlegroups.com>
> Oops, you're right. So it should be something like:
>
> (eval-when (:compile-toplevel :load-toplevel :execute)
>    (setq *readtable* *my-fancy-readtable*))
>

This:

(eval-when (:compile-toplevel :load-toplevel :execute)
(setq *readtable* (copy-readtable))
(set-dispatch-macro-character #\# #\\ #'name-parentheses))

does not work in CMUCL (but does in OpenMCL, CLISP and LispWorks). In
CMUCL, the dispatcher remains redefined.

David
From: Edi Weitz
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <ur7k6lp3v.fsf@agharta.de>
On 27 Jan 2005 09:47:03 -0800, ·············@gmail.com" <············@gmail.com> wrote:

> This:
>
> (eval-when (:compile-toplevel :load-toplevel :execute)
> (setq *readtable* (copy-readtable))
> (set-dispatch-macro-character #\# #\\ #'name-parentheses))
>
> does not work in CMUCL (but does in OpenMCL, CLISP and
> LispWorks). In CMUCL, the dispatcher remains redefined.

Works for me (CMUCL 19a):

  ···@vmware:/tmp$ cat read.lisp 
  (defun name-parentheses (inp c1 c2)
    (declare (ignore c1 c2))
    (let ((c (peek-char nil inp)))
      (cond
        ((alpha-char-p c)
         (ecase (read inp)
           (Lpar #\()
           (Rpar #\))
           (Lsqr #\[)
           (Rsqr #\])
           (Lcur #\{)
           (Rcur #\})
           (Lang #\<)
           (Rang #\>)
           (Tab #\Tab)
           (Space #\Space)
           (Newline #\Newline)))
        (t
         (read-char inp)))))

  (eval-when (:compile-toplevel :load-toplevel :execute)
    (setq *readtable* (copy-readtable))
    (set-dispatch-macro-character #\# #\\ #'name-parentheses))

  (defparameter *lpar* #\Lpar)

  ···@vmware:/tmp$ cmucl
  ; Loading #p"/home/edi/.cmucl-init".
  * (load "read.lisp")

  T
  * *lpar*

  #\(
  * #\Lpar

  Reader error on #<Two-Way Stream, Input = #<Synonym Stream to SYSTEM:*STDIN*>, Output = #<Synonym Stream to SYSTEM:*STDOUT*>>:
  Unrecognized character name: "LPAR"
     [Condition of type READER-ERROR]

Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: ············@gmail.com
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <1106850296.083720.66950@f14g2000cwb.googlegroups.com>
> Works for me (CMUCL 19a):
>   ···@vmware:/tmp$ cmucl
>   ; Loading #p"/home/edi/.cmucl-init".
>   * (load "read.lisp")
>
>   T
>   * *lpar*
>
>   #\(
>   * #\Lpar
>
>   Reader error on #<Two-Way Stream, Input = #<Synonym Stream to
SYSTEM:*STDIN*>, Output = #<Synonym Stream to SYSTEM:*STDOUT*>>:
>   Unrecognized character name: "LPAR"
>      [Condition of type READER-ERROR]
* (compile-file "read.lisp")
...
* #\lpar
#\(
From: Edi Weitz
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <ud5vq4smj.fsf@agharta.de>
On 27 Jan 2005 10:24:56 -0800, ·············@gmail.com" <············@gmail.com> wrote:

>> Works for me (CMUCL 19a):
>>   ···@vmware:/tmp$ cmucl
>>   ; Loading #p"/home/edi/.cmucl-init".
>>   * (load "read.lisp")
>>
>>   T
>>   * *lpar*
>>
>>   #\(
>>   * #\Lpar
>>
>>   Reader error on #<Two-Way Stream, Input = #<Synonym Stream to
> SYSTEM:*STDIN*>, Output = #<Synonym Stream to SYSTEM:*STDOUT*>>:
>>   Unrecognized character name: "LPAR"
>>      [Condition of type READER-ERROR]
> * (compile-file "read.lisp")
> ...
> * #\lpar
> #\(

Yes, that looks like a bug to me.  You should report this to the CMUCL
mailing list.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: ············@gmail.com
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <1106910763.680682.51730@z14g2000cwz.googlegroups.com>
>
> Oops, you're right. So it should be something like:
>
> (eval-when (:compile-toplevel :load-toplevel :execute)
>    (setq *readtable* *my-fancy-readtable*))
>


I don't need :load-toplevel here, just :compile-toplevel and :execute,
do I?


(eval-when (:compile-toplevel :execute)
(setq *readtable* (copy-readtable))
(set-dispatch-macro-character #\# #\\ #'name-parentheses))
From: Pascal Costanza
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <ctd97i$kfg$1@snic.vub.ac.be>
············@gmail.com wrote:
>>Oops, you're right. So it should be something like:
>>
>>(eval-when (:compile-toplevel :load-toplevel :execute)
>>   (setq *readtable* *my-fancy-readtable*))
> 
> I don't need :load-toplevel here, just :compile-toplevel and :execute,
> do I?
> 
> (eval-when (:compile-toplevel :execute)
> (setq *readtable* (copy-readtable))
> (set-dispatch-macro-character #\# #\\ #'name-parentheses))

:load-toplevel is for loading the file when you haven't compiled it 
(yet). I'd keep it in, so to speak. ;)


Pascal
From: ············@gmail.com
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <1106929026.170260.278800@f14g2000cwb.googlegroups.com>
> :load-toplevel is for loading the file when you haven't compiled it
> (yet). I'd keep it in, so to speak. ;)
>

Actually, the other way around. It is for loading a file which IS
compiled. And since the only thing which is defined in the eval-when is
a modification to the readtable, I don't want the code to execute when
I load the compiled module.

It is important, because of four implementations I test it with, one
has difficulty with just this :load-toplevel, which is not needed in
fact.

David
From: Peter Seibel
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <m31xc5s7t8.fsf@javamonkey.com>
·············@gmail.com" <············@gmail.com> writes:

>> :load-toplevel is for loading the file when you haven't compiled it
>> (yet). I'd keep it in, so to speak. ;)
>>
>
> Actually, the other way around. It is for loading a file which IS
> compiled. And since the only thing which is defined in the eval-when is
> a modification to the readtable, I don't want the code to execute when
> I load the compiled module.
>
> It is important, because of four implementations I test it with, one
> has difficulty with just this :load-toplevel, which is not needed in
> fact.

What trouble?

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Christophe Rhodes
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <sqekg567xa.fsf@cam.ac.uk>
Pascal Costanza <··@p-cos.net> writes:

> :load-toplevel is for loading the file when you haven't compiled it
> (yet).

No it isn't.

Christophe
From: Peter Seibel
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <m3651hs7u2.fsf@javamonkey.com>
Pascal Costanza <··@p-cos.net> writes:

> ············@gmail.com wrote:
>>>Oops, you're right. So it should be something like:
>>>
>>>(eval-when (:compile-toplevel :load-toplevel :execute)
>>>   (setq *readtable* *my-fancy-readtable*))
>> I don't need :load-toplevel here, just :compile-toplevel and
>> :execute,
>> do I?
>> (eval-when (:compile-toplevel :execute)
>> (setq *readtable* (copy-readtable))
>> (set-dispatch-macro-character #\# #\\ #'name-parentheses))
>
> :load-toplevel is for loading the file when you haven't compiled it
> (yet). I'd keep it in, so to speak. ;)

No, :load-toplevel is for loading the file when you *have* compiled
it. I.e. when you're loading the FASL produced by COMPILE-FILE. Which
might matter in this case if your code happens to contain calls to
READ-FROM-STRING that get evaluated as part of some top-level form.
Anyway, there's little reason to leave it out and leaving it in keeps
(load "foo.lisp") and (load (compile-file "foo.lisp")) (more)
consistent.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: ············@gmail.com
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <1106940941.687812.153780@c13g2000cwb.googlegroups.com>
An implementation cannot dump the code in eval-when into the compiled
file and warns that the compiled file will not be generated, unless I
leave :load-toplevel out.
From: Peter Seibel
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <m3hdl1qqzm.fsf@javamonkey.com>
·············@gmail.com" <············@gmail.com> writes:

> An implementation cannot dump the code in eval-when into the compiled
> file and warns that the compiled file will not be generated, unless I
> leave :load-toplevel out.

Can you show us exactly what code you have that these impls complain
about--I've seen several different code snippets in this thread.

-Peter


-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Pascal Costanza
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <cteakq$3jb$1@snic.vub.ac.be>
Peter Seibel wrote:
> Pascal Costanza <··@p-cos.net> writes:
> 
>>:load-toplevel is for loading the file when you haven't compiled it
>>(yet). I'd keep it in, so to speak. ;)
> 
> No, :load-toplevel is for loading the file when you *have* compiled
> it. I.e. when you're loading the FASL produced by COMPILE-FILE. Which
> might matter in this case if your code happens to contain calls to
> READ-FROM-STRING that get evaluated as part of some top-level form.
> Anyway, there's little reason to leave it out and leaving it in keeps
> (load "foo.lisp") and (load (compile-file "foo.lisp")) (more)
> consistent.

OK, thanks for the correction.


Pascal
From: Damien Kick
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <hdkzwwsy.fsf@email.mot.com>
Pascal Costanza <··@p-cos.net> writes:

> ············@gmail.com wrote:
> 
> > Then, I define functions in the package, and at the end want to restore
> > the reader:
> > #.(set-dispatch-macro-character #\# #\\
> 
> > (get-dispatch-macro-character #\# #\\ (copy-readtable nil)))
> 
> I think it's better to install a new macro character like this:
> 
> (eval-when (:compile-toplevel :load-toplevel :execute)
>    (set-dispatch-macro-character ...))
> 
> You don't need to restore the reader, this is ensured by Common
> Lisp.  See the issue IN-SYNTAX and the specs for COMPILE-FILE and
> LOAD in the HyperSpec.

I'm not finding the behavior I'd expect, after reading your above
comments, from CMUCL 19a .

    PG-USER> !'(a b c)
    ; Evaluation aborted

Normal *READTABLE*.

    PG-USER> (describe 'sh)
    SH is an external symbol in the UNCOMMON-LISP package.
    Function: #<Function SH {8048AC79}>
    Function arguments:
      (command)
    Function documentation:
      Process elements of COMMAND with format control string ~A as
    arguments to be passed to RUN-PROGRAM, returning the output of the
    command as astring and the process itself, after having been passed to
    PROCESS-CLOSE.
    Its defined argument types are:
      (T)
    Its result type is:
      (VALUES (OR (ARRAY BASE-CHAR) NULL) (OR EXTENSIONS::PROCESS NULL))
    On Saturday, 1/29/05 05:42:48 pm CST it was compiled from:
    /home/kick/lisp/uncommon-lisp/kick-misc.lisp
      Created: Saturday, 1/29/05 04:37:29 pm CST

    ; No value
    PG-USER> (sh '("cat" "kick-reader-macros.lisp"))
    "(in-package #:uncommon-lisp)

    (defun |!' READER| (stream char n-arg)
      (declare (ignore char n-arg))
      (let ((*readtable* (copy-readtable *readtable*)))
        (setf (readtable-case *readtable*) :preserve)
        (funcall (get-macro-character #\\') stream #\\')))

    (defun |!` READER| (stream char n-arg)
      (declare (ignore char n-arg))
      (let ((*readtable* (copy-readtable *readtable*)))
        (setf (readtable-case *readtable*) :preserve)
        (funcall (get-macro-character #\\`) stream #\\`)))

    (defun |!$ READER| (stream char n-arg)
      (declare (ignore char))
      `(sh ,(|!` READER| stream #\\` n-arg)))
    "
    #<process 17405 :EXITED>

I've defined some functions to be used as reader macro functions.  In
the following file, I establish them as reader macros inside of an
EVAL-WHEN form, expecting their establishment to be valid only within
the "scope" of the file.

    PG-USER> (sh '("cat" "kick-reader-macros-tests.lisp"))
    "(in-package #:pg-user)

    (eval-when (:compile-toplevel :load-toplevel :execute)
      (setq *readtable* (copy-readtable nil))
      (make-dispatch-macro-character #\\!)
      (set-dispatch-macro-character #\\! #\\' #'|!' READER|)
      (set-dispatch-macro-character #\\! #\\` #'|!` READER|)
      (set-dispatch-macro-character #\\! #\\$ #'|!$ READER|))

    (defun test0 ()
      !'(UPPER lower CamelCase))

    (defun test1 ()
      (let ((x 69))
        !`(x ,X y z)))

    (defun test2 ()
      (sh !'(ls)))

    (defun test3 ()
      !$(ls \\-l))
    "
    #<process 18107 :EXITED>
    PG-USER> (setq *readtable* *remember*)
    #<READTABLE {40FA654D}>

We remember the *READTABLE* in affect before loading and compiling the
file.

    PG-USER> (load (compile-file #p"kick-reader-macros-tests"))

    ; Python version 1.1, VM version UltraSparc/Solaris 7 on 29 JAN 05 06:09:34 pm.
    ; Compiling: /home/kick/lisp/uncommon-lisp/kick-reader-macros-tests.lisp 29 JAN 05 05:59:25 pm

    ; Converted TEST0.
    ; Compiling DEFUN TEST0: 
    ; Converted TEST1.
    ; Compiling DEFUN TEST1: 
    ; Converted TEST2.
    ; Compiling DEFUN TEST2: 
    ; Converted TEST3.
    ; Compiling DEFUN TEST3: 
    ; Byte Compiling Top-Level Form: 

    ; /home/kick/lisp/uncommon-lisp/kick-reader-macros-tests.sparcf written.
    T
    ; Compilation finished in 0:00:00.
    ; Loading #p"/home/kick/lisp/uncommon-lisp/kick-reader-macros-tests.sparcf".
    PG-USER> (eq *readtable* *remember*)
    NIL

However, as the above interaction shows, after loading and compiling
the file, the *READTABLE* has been adjusted in the REPL top-level.
FWIW, these interaction snippets are being copy-n-pasted from a SLIME
REPL but I also tested LOAD/COMPILE-FILE in a raw CMUCL REPL,
observing the same effect.

    PG-USER> (test3)
    ; [... values snipped for brevity ...]

This worked as I expected.  However...

    PG-USER> !'(a b c)
    (|a| |b| |c|)

I didn't want these reader macros to "bleed" into the REPL top-level.
I have to "manually" restore the *READTABLE*.

    PG-USER> (setq *readtable* *remember*)
    #<READTABLE {80008CED}>
    PG-USER> !'(a b c)
    ; Evaluation aborted
    PG-USER> 

Is the following a bug in my understanding of Pascal's post, a bug in
Pascal's post, or a bug in the Lisp implementation I'm using?  My
reading of that CLHS agrees with my reading of Pascal's post; i.e. I'm
leaning towards there being a bug in the Lisp implementation.  Allegro
CL Trial Edition 6.2 seems to support my understanding of that CLHS
section.

    PG-USER(24): 
    ; Fast loading H:\Personal\lisp\kick-reader-macros.fasl

    PG-USER(24): 
    Warning: While compiling these undefined functions were referenced: SH.
    ; Fast loading H:\Personal\lisp\kick-reader-macros-test.fasl

    PG-USER(24): !'(a b c)
    Error: Attempt to take the value of the unbound variable `!'.
    [condition type: UNBOUND-VARIABLE]
    PG-USER(25): (test0)
    (UPPER |lower| |CamelCase|)
    PG-USER(26): 

For what its worth:

    PG-USER> (lisp-implementation-type)
    "CMU Common Lisp"
    PG-USER> (lisp-implementation-version)
    "19a"
    PG-USER> (machine-version)
    "Ultrasparc"
    PG-USER> (software-version)
    "5.8"

BTW, the REPL top-level *READTABLE* only seems to be affected by
COMPILE-FILE.

    PG-USER> (load "kick-reader-macros-tests")
    ; Loading #p"/home/kick/lisp/uncommon-lisp/kick-reader-macros-tests.sparcf".
    T
    PG-USER> !'(a b c)
    ; Evaluation aborted

Reloading didn't affect *READTABLE*.

    PG-USER> (test0)
    (UPPER |lower| |CamelCase|)
    PG-USER> 

But TEST0 still works like I'd expected.
From: ············@gmail.com
Subject: Re: set/get-dispatch-macro-character
Date: 
Message-ID: <1107088744.825414.247680@f14g2000cwb.googlegroups.com>
> I'm not finding the behavior I'd expect, after reading your above
> comments, from CMUCL 19a .
>

It is a bug in CMUCL . I discovered it too, and sent a link to this
discussion to their mailing list, but didn't hear anything back.

David