From: Peter Seibel
Subject: Embedding arbitrary chars in string literals
Date: 
Message-ID: <m31y0hqty4.fsf@javamonkey.com>
Is there any way to embed arbitrary characters into strings read with
the " read-macro using just the standard characters. I.e. some way to
write a the equivalent of:

 (concatenate 'string "foo" (string (code-char 13)) "bar")

using just a double-quoted string?

BTW, I know I can write strings with actual newlines in them such as:

"foo
bar"

I'm looking for a more general way, equivalent to C or Java's ability
to use \ooo where 'o' is an octal digit. (I also understand that what
character a given number would encode is implementation dependent.)

-Peter


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

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra

From: Adam Warner
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <pan.2003.04.05.11.17.05.643007@consulting.net.nz>
Hi Peter Seibel,

> I'm looking for a more general way, equivalent to C or Java's ability to
> use \ooo where 'o' is an octal digit. (I also understand that what
> character a given number would encode is implementation dependent.)

Common Lisp is easily powerful enough to support this in an implementation
independent way. All you have to do is write your own read macro for #\".
Try to avoid giving \(, \[, \{ any separating meaning as this notation is
necessary to overcome brain dead Emacs regular expressions that think any
( character at the start of a line is the start of a (defun etc. (even
when one is clearly in the middle of a string definition).

As this will break standard syntax you might consider using a different
character to denote such strings.

Here's an example of redefined double-quote syntax:
https://macrology.co.nz/lisp/triple-double-quote.html

Regards,
Adam
From: Peter Seibel
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <m3wui8ps9y.fsf@javamonkey.com>
"Adam Warner" <······@consulting.net.nz> writes:

> Hi Peter Seibel,
> 
> > I'm looking for a more general way, equivalent to C or Java's ability to
> > use \ooo where 'o' is an octal digit. (I also understand that what
> > character a given number would encode is implementation dependent.)
> 
> Common Lisp is easily powerful enough to support this in an
> implementation independent way. All you have to do is write your own
> read macro for #\". Try to avoid giving \(, \[, \{ any separating
> meaning as this notation is necessary to overcome brain dead Emacs
> regular expressions that think any ( character at the start of a
> line is the start of a (defun etc. (even when one is clearly in the
> middle of a string definition).

Yeah. I had thought of that. I was just making sure I hadn't missed
something about the standard doublequote read macro.

> As this will break standard syntax you might consider using a
> different character to denote such strings.

Along those lines, what's the best way to actually use non-standard
syntax. I assume if at the top of some file I muck with the readtable,
if I load the file the readtable is going to stay mucked unless I take
explict steps to restore the original one. Is that right?

I suppose one could, the cost of causing everything to be indented a
bit more than normal wrap a whole file in:

  (let ((*readtable* *my-funky-readtable*))

     ;; use funky syntax in here

         )

Or is there some other standard technique or idiom?

-Peter

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

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra
From: Peter Seibel
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <m3wui8o00f.fsf@javamonkey.com>
Peter Seibel <·····@javamonkey.com> writes:

> I suppose one could, the cost of causing everything to be indented a
> bit more than normal wrap a whole file in:
> 
>   (let ((*readtable* *my-funky-readtable*))
> 
>      ;; use funky syntax in here
> 
>          )

Uh, never mind. As someone pointed out to me in email, that doesn't
work at all as the LET doesn't have any effect at read time. Duh.

-Peter

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

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra
From: Adam Warner
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <pan.2003.04.06.02.21.55.269003@consulting.net.nz>
Hi Peter Seibel,

> Peter Seibel <·····@javamonkey.com> writes:
> 
>> I suppose one could, the cost of causing everything to be indented a
>> bit more than normal wrap a whole file in:
>> 
>>   (let ((*readtable* *my-funky-readtable*))
>> 
>>      ;; use funky syntax in here
>> 
>>          )
> 
> Uh, never mind. As someone pointed out to me in email, that doesn't
> work at all as the LET doesn't have any effect at read time. Duh.

Thanks for reinforcing along with JP Massar that let does bind variables
proclaimed special and alters the value of the proclaimed variable for as
long as the binding is in force. I did not understand this difference
between declarations and global proclamations.

It is this exact readtable issue that induced my misunderstanding long ago
:-) I'm glad to know the true cause for why the code will not work!

Regards,
Adam
From: Adam Warner
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <pan.2003.04.05.23.27.43.343770@consulting.net.nz>
Hi Peter Seibel,

> "Adam Warner" <······@consulting.net.nz> writes:
> 
>> Hi Peter Seibel,
>> 
>> > I'm looking for a more general way, equivalent to C or Java's ability
>> > to use \ooo where 'o' is an octal digit. (I also understand that what
>> > character a given number would encode is implementation dependent.)
>> 
>> Common Lisp is easily powerful enough to support this in an
>> implementation independent way. All you have to do is write your own
>> read macro for #\". Try to avoid giving \(, \[, \{ any separating
>> meaning as this notation is necessary to overcome brain dead Emacs
>> regular expressions that think any ( character at the start of a line
>> is the start of a (defun etc. (even when one is clearly in the middle
>> of a string definition).
> 
> Yeah. I had thought of that. I was just making sure I hadn't missed
> something about the standard doublequote read macro.
> 
>> As this will break standard syntax you might consider using a different
>> character to denote such strings.
> 
> Along those lines, what's the best way to actually use non-standard
> syntax. I assume if at the top of some file I muck with the readtable,
> if I load the file the readtable is going to stay mucked unless I take
> explict steps to restore the original one. Is that right?
> 
> I suppose one could, the cost of causing everything to be indented a bit
> more than normal wrap a whole file in:
> 
>   (let ((*readtable* *my-funky-readtable*))
> 
>      ;; use funky syntax in here
> 
>          )
> 
> Or is there some other standard technique or idiom?

*READTABLE* is a dynamic variable and here you are trying to change it
simply by shadowing it with a lexical variable! The proper approach is
save a copy of the readtable using COPY-READTABLE (within in a lexical
variable is fine) and then change the dynamic variable *READTABLE*. You
can then reset the readtable to its original value by resetting
*READTABLE* to the saved default. Of course all of this can be wrapped in
a nice looking macro. So you could end up with (funky-syntax "....").

Perhaps alternatively, see 2.1.4 of the HyperSpec for which ASCII
characters are reserved for use by the user as (for example) unescaped
macro characters, e.g. you might consider delimiting your funky strings
with [ ]. The only time this would break is if some other user's package
also makes use of the same macro characters. In Unicode source code you
have potentially thousands of useful macro characters. Even iso-8859-1 has
useful ones like � and �.

Regards,
Adam
From: Peter Seibel
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <m3brzkpk32.fsf@javamonkey.com>
"Adam Warner" <······@consulting.net.nz> writes:

> Hi Peter Seibel,

> > I suppose one could, the cost of causing everything to be indented a bit
> > more than normal wrap a whole file in:
> > 
> >   (let ((*readtable* *my-funky-readtable*))
> > 
> >      ;; use funky syntax in here
> > 
> >          )
> > 
> > Or is there some other standard technique or idiom?
> 
> *READTABLE* is a dynamic variable and here you are trying to change it
> simply by shadowing it with a lexical variable!

Huh? LET works for special variables too.

    CL-USER(1773): (defun foo () (format t "Readtable is ~s~%" *readtable*))
    FOO
    CL-USER(1774): (foo)
    Readtable is #<readtable @ #x7127a97a>
    NIL
    CL-USER(1775): (let ((*readtable* (copy-readtable))) (foo))
    Readtable is #<readtable @ #x71cfec0a> ;; <--- note it has changed
    NIL
    CL-USER(1776): (foo)
    Readtable is #<readtable @ #x7127a97a> ;; <--- note it's back to the original value.
    NIL

See the dictionary entry for SPECIAL. (In 3.8 The Evaluation and
Compilation Dictionary).

> Perhaps alternatively, see 2.1.4 of the HyperSpec for which ASCII
> characters are reserved for use by the user as (for example) unescaped
> macro characters, e.g. you might consider delimiting your funky strings
> with [ ]. The only time this would break is if some other user's package
> also makes use of the same macro characters. In Unicode source code you
> have potentially thousands of useful macro characters. Even iso-8859-1 has
> useful ones like � and �.

That's the exact problem I'm trying to avoid--I don't want to have my
system as a whole dependent on hoping that I don't happen to collide
with some other package that happens to use the same characters for
their special syntax.

-Peter

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

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra
From: Adam Warner
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <pan.2003.04.06.00.31.45.755126@consulting.net.nz>
Hi Peter Seibel,

>> > I suppose one could, the cost of causing everything to be indented a bit
>> > more than normal wrap a whole file in:
>> > 
>> >   (let ((*readtable* *my-funky-readtable*))
>> > 
>> >      ;; use funky syntax in here
>> > 
>> >          )
>> > 
>> > Or is there some other standard technique or idiom?
>> 
>> *READTABLE* is a dynamic variable and here you are trying to change it
>> simply by shadowing it with a lexical variable!
> 
> Huh? LET works for special variables too.
> 
>     CL-USER(1773): (defun foo () (format t "Readtable is ~s~%" *readtable*))
>     FOO
>     CL-USER(1774): (foo)
>     Readtable is #<readtable @ #x7127a97a>
>     NIL
>     CL-USER(1775): (let ((*readtable* (copy-readtable))) (foo))
>     Readtable is #<readtable @ #x71cfec0a> ;; <--- note it has changed
>     NIL
>     CL-USER(1776): (foo)
>     Readtable is #<readtable @ #x7127a97a> ;; <--- note it's back to the original value.
>     NIL
> 
> See the dictionary entry for SPECIAL. (In 3.8 The Evaluation and
> Compilation Dictionary).

Thanks for the reference. What part of "A special declaration does not
affect inner bindings of a var; the inner bindings implicitly shadow a
special declaration and must be explicitly re-declared to be special." do
I misunderstand?

Regards,
Adam
From: JP Massar
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <3e8f8618.96877057@netnews.attbi.com>
On Sun, 06 Apr 2003 12:31:50 +1200, "Adam Warner"
<······@consulting.net.nz> wrote:

>Hi Peter Seibel,
>
>>> > I suppose one could, the cost of causing everything to be indented a bit
>>> > more than normal wrap a whole file in:
>>> > 
>>> >   (let ((*readtable* *my-funky-readtable*))
>>> > 
>>> >      ;; use funky syntax in here
>>> > 
>>> >          )
>>> > 
>>> > Or is there some other standard technique or idiom?
>>> 
>>> *READTABLE* is a dynamic variable and here you are trying to change it
>>> simply by shadowing it with a lexical variable!
>> 
>> Huh? LET works for special variables too.
>> 
>>     CL-USER(1773): (defun foo () (format t "Readtable is ~s~%" *readtable*))
>>     FOO
>>     CL-USER(1774): (foo)
>>     Readtable is #<readtable @ #x7127a97a>
>>     NIL
>>     CL-USER(1775): (let ((*readtable* (copy-readtable))) (foo))
>>     Readtable is #<readtable @ #x71cfec0a> ;; <--- note it has changed
>>     NIL
>>     CL-USER(1776): (foo)
>>     Readtable is #<readtable @ #x7127a97a> ;; <--- note it's back to the original value.
>>     NIL
>> 
>> See the dictionary entry for SPECIAL. (In 3.8 The Evaluation and
>> Compilation Dictionary).
>
>Thanks for the reference. What part of "A special declaration does not
>affect inner bindings of a var; the inner bindings implicitly shadow a
>special declaration and must be explicitly re-declared to be special." do
>I misunderstand?
>
 
Maybe you are confusing a special declaration with a special
proclamation?  *READTABLE* is globally proclaimed special.

(I'm not asserting you are being confused, but if there is some
confusion between you and Peter this might be part of it)
From: Peter Seibel
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <m365pspf6j.fsf@javamonkey.com>
"Adam Warner" <······@consulting.net.nz> writes:

> Hi Peter Seibel,
> 
> >> > I suppose one could, the cost of causing everything to be indented a bit
> >> > more than normal wrap a whole file in:
> >> > 
> >> >   (let ((*readtable* *my-funky-readtable*))
> >> > 
> >> >      ;; use funky syntax in here
> >> > 
> >> >          )
> >> > 
> >> > Or is there some other standard technique or idiom?
> >> 
> >> *READTABLE* is a dynamic variable and here you are trying to change it
> >> simply by shadowing it with a lexical variable!
> > 
> > Huh? LET works for special variables too.
> > 
> >     CL-USER(1773): (defun foo () (format t "Readtable is ~s~%" *readtable*))
> >     FOO
> >     CL-USER(1774): (foo)
> >     Readtable is #<readtable @ #x7127a97a>
> >     NIL
> >     CL-USER(1775): (let ((*readtable* (copy-readtable))) (foo))
> >     Readtable is #<readtable @ #x71cfec0a> ;; <--- note it has changed
> >     NIL
> >     CL-USER(1776): (foo)
> >     Readtable is #<readtable @ #x7127a97a> ;; <--- note it's back to the original value.
> >     NIL
> > 
> > See the dictionary entry for SPECIAL. (In 3.8 The Evaluation and
> > Compilation Dictionary).
> 
> Thanks for the reference. What part of "A special declaration does
> not affect inner bindings of a var; the inner bindings implicitly
> shadow a special declaration and must be explicitly re-declared to
> be special." do I misunderstand?

I think the relevant bit from the SPECIAL entry is: "When used in a
proclamation, a special declaration specifier applies to all bindings
as well as to all references of the mentioned variables."

Since *readtable* is globally special, this sentence applies, as I
understand it.

Thus:

  CL-USER(2050): (defvar *x* 10)
  *X*
  CL-USER(2053): (defun foo () (print *x*))
  FOO
  CL-USER(2062): (foo)
  10 
  10
  CL-USER(2063): (let ((*x* 20)) (foo))
  20 
  20
  CL-USER(2068): (defun bar () (print *y*))
  BAR
  CL-USER(2073): (let ((*y* 10)) (bar))
  Error: Attempt to take the value of the unbound variable `*Y*'.
    [condition type: UNBOUND-VARIABLE]

  Restart actions (select using :continue):
   0: Try evaluating *Y* again.
   1: Set the symbol-value of *Y* and use its value.
   2: Use a value without setting *Y*.
   3: Return to Top Level (an "abort" restart).
   4: Abort entirely from this process.
  [1] CL-USER(2078): :res
  CL-USER(2079): (let ((*y* 10)) (declare (special *y*)) (bar))
  10 
  10
  CL-USER(2086): (defun baz () (let ((*y* 20)) (print *y*) (bar)))
  BAZ
  CL-USER(2095): (let ((*y* 10)) (declare (special *y*)) (baz))
  20 ;; <-- lexcially shadowed by let in BAZ
  10 ;; <-- BAR still picks up the special version.
  10
  CL-USER(2096): 

-Peter


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

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra
From: Thomas A. Russ
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <ymi1y0bpad5.fsf@sevak.isi.edu>
Peter Seibel <·····@javamonkey.com> writes:

 > Thus:
 > 
 >   CL-USER(2050): (defvar *x* 10)
 >   *X*
 >   CL-USER(2053): (defun foo () (print *x*))
 >   FOO
 >   CL-USER(2062): (foo)
 >   10 
 >   10
 >   CL-USER(2063): (let ((*x* 20)) (foo))
 >   20 
 >   20
 >   CL-USER(2068): (defun bar () (print *y*))
 >   BAR

To avoid common compile notes about *Y* being assumed special
it would be better to do

(defun bar () (declare (special *y*)) (print *y*))

but that doesn't affect the rest of the example at all.  It does make it
clear that *Y* IS considered special inside BAR.

 >   CL-USER(2073): (let ((*y* 10)) (bar))
 >   Error: Attempt to take the value of the unbound variable `*Y*'.
 >     [condition type: UNBOUND-VARIABLE]
 > 
 >   Restart actions (select using :continue):
 >    0: Try evaluating *Y* again.
 >    1: Set the symbol-value of *Y* and use its value.
 >    2: Use a value without setting *Y*.
 >    3: Return to Top Level (an "abort" restart).
 >    4: Abort entirely from this process.
 >   [1] CL-USER(2078): :res
 >   CL-USER(2079): (let ((*y* 10)) (declare (special *y*)) (bar))
 >   10 
 >   10
 >   CL-USER(2086): (defun baz () (let ((*y* 20)) (print *y*) (bar)))
 >   BAZ
 >   CL-USER(2095): (let ((*y* 10)) (declare (special *y*)) (baz))
 >   20 ;; <-- lexcially shadowed by let in BAZ
 >   10 ;; <-- BAR still picks up the special version.
 >   10
 >   CL-USER(2096): 
 > 
 > -Peter

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Steven M. Haflich
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <3E8F9EAA.8090507@alum.mit.edu>
Adam Warner wrote:

>>>>  (let ((*readtable* *my-funky-readtable*))
>>>>
>>>>     ;; use funky syntax in here
>>>>
>>>>         )

> Thanks for the reference. What part of "A special declaration does not
> affect inner bindings of a var; the inner bindings implicitly shadow a
> special declaration and must be explicitly re-declared to be special." do
> I misunderstand?

I see no special declaration in this code.  A special declaration is a
lexical property of code within the extent of the declaration:

  (defun foo () (declare (special x)) (print x))

  (let ((x 1))		; This binds as a special
    (declare (special x))
    (foo)
    (print x)
    (let ((x 2))		; This binds as a lexical
      (foo)
      (print x))
  (values))

This code fragment prints 1, 1, 1, 2.

A variable may be declaimed everywhere special using declaim/proclaim,
or defvar/defparameter/defconstant.  A variable may be declared special
for a particular lexical range using declare.  An inner binding and
references lexically inside that binding are not affected by an outer
declaration, but are both affected by a global declamation.

Now, if that is settled, there is a more interesting issue to consider
about wrapping a binding of *readtable* around the entire contents of
a file.  This may change the semantics of loading or compiling the
file in subtle ways.  Normally the compiler (and possible also the
interpreted file loader) reads a single top-level form and processes
is before reading the next form.  But if you wrap the entire content
of the file in a single top-level form, the entire file is read before
anything is processed.  Indeed, the file compiler must compile the
entire file before executing any of it.  That means that macros
defined earlier in the file will _not_ be available to the file compiler
when functions later in the file are compiled.  Ditto for files that
mess with readtable syntax of radix or *package* or whatever within the
file.  This would be incompatible with many existing Lisp applications.

Note that load and compile-file are defined to bind *readtable* and
*package* to themselves.  Therefore, the conventional way to set the
package for the remainder of a file is

   (in-package :foo)

which expands to something like

   (eval-when (compile load eval) (setf *package* (find-package :foo)))

Similarly for *readtable*, except that there is no ANS operator for
rendezvous with a particular readtable.  Lisp Machines and ACL have
a named-readtable facility, but in general:

   (eval-when (compile eval)
     (setf *readtable* ... code that finds or constructs a readtable ...))
From: Peter Seibel
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <m3el4gnsuq.fsf@javamonkey.com>
"Steven M. Haflich" <·················@alum.mit.edu> writes:

> Note that load and compile-file are defined to bind *readtable* and
> *package* to themselves. Therefore, the conventional way to set the
> package for the remainder of a file is
> 
>    (in-package :foo)
> 
> which expands to something like
> 
>    (eval-when (compile load eval) (setf *package* (find-package :foo)))
> 
> Similarly for *readtable*, except that there is no ANS operator for
> rendezvous with a particular readtable. Lisp Machines and ACL have a
> named-readtable facility, but in general:
> 
>    (eval-when (compile eval)
>      (setf *readtable* ... code that finds or constructs a readtable ...))

And then, if you want to be a good citizen, at the end of the file,
you'll probably want to do something like this, right?

  (eval-when (:compile-toplevel :execute)
    (setf *readtable* ... squirreled away original readtable ...))

Or maybe wrap your call to COMPILE-FILE like:

  (let ((*readtable* (copy-readtable))) (compile-file "foo.lisp"))

so the mucking around with *readtable* within the file doesn't linger
after you're done and affect other files. Is that more or less right?

-Peter

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

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra
From: Rob Warnock
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <k46cnTVb1s_bZxKjXTWc-g@speakeasy.net>
Peter Seibel  <·····@javamonkey.com> wrote:
+---------------
| "Steven M. Haflich" <·················@alum.mit.edu> writes:
| > Note that load and compile-file are defined to bind *readtable* and
| > *package* to themselves. ...
| > 
| > Similarly for *readtable*...
| 
| And then, if you want to be a good citizen, at the end of the file,
| you'll probably want to do something like this, right?
| 
|   (eval-when (:compile-toplevel :execute)
|     (setf *readtable* ... squirreled away original readtable ...))
| 
| Or maybe wrap your call to COMPILE-FILE like:
| 
|   (let ((*readtable* (copy-readtable))) (compile-file "foo.lisp"))
| 
| so the mucking around with *readtable* within the file doesn't linger
| after you're done and affect other files. Is that more or less right?
+---------------

Uh... Look again at what Steven wrote above [extra emphasis added]:

	Note that load and compile-file are __DEFINED__ to bind
	*readtable* and *package* to themselves.

From <URL:http://www.lispworks.com/reference/HyperSpec/Body/f_load.htm>:

	Function LOAD
	...
	load binds *readtable* and *package* to the values they held
	before loading the file.

From <URL:http://www.lispworks.com/reference/HyperSpec/Body/f_cmp_fi.htm>:

	Function COMPILE-FILE
	...
	compile-file binds *readtable* and *package* to the values they
	held before processing the file.

Therefore the values of both variables are automatically restored to
their previous values after LOAD'ing or COMPILE-FILE'ing a file, and
thus it is perfectly safe to SETF them in the file without restoring
them in the file.

Of course, one should be careful of the distinction between binding/assigning
a variable versus changing the object it is bound/assigned to, and always
mutate a *copy* of the current readtable rather than mutating the readtable
object which was current when the file started loading. Which is why Steven
wrote this:

+---------------
| >    (eval-when (compile eval)
| >      (setf *readtable* ... code that finds or constructs a readtable ...))
+---------------

instead of this:

	(eval-when (compile eval)
	  (set-dispatch-macro-character ...blah...blah...)
	  (set-macro-character ...blah...blah...)
	  ...
	  )

That is, as long as the code at the top of your file looks something
like this:

	(eval-when (compile eval)
	  (setf *readtable* (copy-readtable))  ;or maybe (copy-readtable nil)
	  (set-dispatch-macro-character ...blah...blah...)
	  (set-macro-character ...blah...blah...)
	  ...
	  )
	;;; Now use special syntax...

you won't need to do anything at all at the end of the file *or* in any
program which loads or compiles the file.


-Rob

-----
Rob Warnock, PP-ASEL-IA		<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Peter Seibel
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <m3adf3or0o.fsf@javamonkey.com>
····@rpw3.org (Rob Warnock) writes:

> Peter Seibel  <·····@javamonkey.com> wrote:
> +---------------
> | "Steven M. Haflich" <·················@alum.mit.edu> writes:
> | > Note that load and compile-file are defined to bind *readtable* and
> | > *package* to themselves. ...
> | > 
> | > Similarly for *readtable*...
> | 
> | And then, if you want to be a good citizen, at the end of the file,
> | you'll probably want to do something like this, right?
> | 
> |   (eval-when (:compile-toplevel :execute)
> |     (setf *readtable* ... squirreled away original readtable ...))
> | 
> | Or maybe wrap your call to COMPILE-FILE like:
> | 
> |   (let ((*readtable* (copy-readtable))) (compile-file "foo.lisp"))
> | 
> | so the mucking around with *readtable* within the file doesn't linger
> | after you're done and affect other files. Is that more or less right?
> +---------------
> 
> Uh... Look again at what Steven wrote above [extra emphasis added]:
> 
> 	Note that load and compile-file are __DEFINED__ to bind
> 	*readtable* and *package* to themselves.

Ah. Great. I'm an idiot. Thanks. That makes me a lot happier about
read macros. Cool.

-Peter

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

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra
From: Tim Bradshaw
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <ey3llynx1rb.fsf@cley.com>
* Adam Warner wrote:

> *READTABLE* is a dynamic variable and here you are trying to change it
> simply by shadowing it with a lexical variable! The proper approach is
> save a copy of the readtable using COPY-READTABLE (within in a lexical
> variable is fine) and then change the dynamic variable *READTABLE*. You
> can then reset the readtable to its original value by resetting
> *READTABLE* to the saved default. Of course all of this can be wrapped in
> a nice looking macro. So you could end up with (funky-syntax
> "....").

This is all *completely* confused. The binding of *READTABLE* is
dynamic.  but this can't work because READ has already read the whole
form by the time the macro is seen.  You need the binding to happen at
*read* time, no later.  Have a look at my hacky read-a-form-in-a-package
thing, which lets you say, for instance:

    ·@foo (this form is read in package "FOO")

for ideas on how you might do this.

--tim
From: Adam Warner
Subject: Re: Embedding arbitrary chars in string literals
Date: 
Message-ID: <pan.2003.04.05.11.31.01.29379@consulting.net.nz>
> (I also understand that what character a given number would encode is
> implementation dependent.)
> 
> Common Lisp is easily powerful enough to support this in an
> implementation independent way.

Sorry, the reader macro would be implementation independent. The character
codes may not be without more work. Just define all character codes under
128 to be ASCII codes and add in any per-implementation transformation if
necessary. The end result will be a macro that works consistently across
implementations even though it contains implementation specific code.

Regards,
Adam