From: Marco Baringer
Subject: per file messing with the read table
Date: 
Message-ID: <m2llqyyhh7.fsf@bese.it>
I'd like to use a personal read macro and I want to make sure that any
changes I make to the readtable doesn't interfere with other code
(which will be LOADed seperatly from other files).

I know that load rebinds *readtable* and my initial tests seem to say
that if the first thing I do in my file is:

(eval-when (:compile-toplevel :load-toplevel :execute)
  (copy-readtable *readtable* *readtable*))

Then i can do whatever weird voodoo I want and the next file which
gets loaded will not see the changes.

Is this correct? Is there anything I should look out for? Is this a
"good" idea?

-- 
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
     -Leonard Cohen

From: ·············@comcast.net
Subject: Re: per file messing with the read table
Date: 
Message-ID: <r80qln81.fsf@comcast.net>
Marco Baringer <··@bese.it> writes:

> I'd like to use a personal read macro and I want to make sure that any
> changes I make to the readtable doesn't interfere with other code
> (which will be LOADed seperatly from other files).
>
> I know that load rebinds *readtable* and my initial tests seem to say
> that if the first thing I do in my file is:
>
> (eval-when (:compile-toplevel :load-toplevel :execute)
>   (copy-readtable *readtable* *readtable*))
>
> Then i can do whatever weird voodoo I want and the next file which
> gets loaded will not see the changes.
>
> Is this correct?  Is there anything I should look out for? 

Here's what I do.  It's probably overkill for what you want, though.

I have a file that implements the reader for the funny syntax.
It is compiled and loaded fairly early on, but it doesn't mess
with the readtable.  It does this:

    (defvar *original-readtable* nil)
    (defvar *special-readtable* nil)

    (defun enable-special-syntax ()
      (setq *original-readtable* *readtable*
            *readtable* (or *special-readtable* (copy-readtable)))

      (set-macro-character ...)
      ...)

    (defun disable-special-syntax ()
      (setq *readtable* *original-readtable*))

Then, in the file that uses the funny syntax, I write

    (eval-when (:compile-toplevel :load-toplevel :execute)
      (enable-special-syntax))

    ;;; stuff with special syntax goes here

    (eval-when (:compile-toplevel :load-toplevel :execute)
      (disable-special-syntax))

> Is this a "good" idea?

Tough question.  The answer is, `in general, don't mess with the
readtable', but sometimes it is exactly the right thing.

At ITASoftware, a lot of hacking is done on TLAs (three letter
acronyms).  Airports and cities all have canonical TLAs.  The obvious
representation of a TLA as a string would be space and time
inefficient, so there is a mapping from a TLA to a compact form.
Instead of riddling the code with things like
 #.(string-to-TLA "BOS"), I wrote a read macro so #!BOS would 
read as the compact form.

On the configuration management project I'm working on, we hack a lot
of distributed object identifiers.  These are structured objects, but
they are interned.  Since they are used so frequently I hacked the
reader such that [repository.object.24] was readable as distributed id.
This saves a lot of this sort of stuff:

 #.(make-instance 'distributed-id :repository "repository"
                                  :class 'object
                                  :serial-number 24)

Maybe the correct `rule of thumb' is this:  if you find yourself writing

  #.(create-something-from-a-printed-representation)

all over the place, then you really could use a reader macro.
From: Marco Baringer
Subject: Re: per file messing with the read table
Date: 
Message-ID: <m2ism2wul4.fsf@bese.it>
·············@comcast.net writes:

> Maybe the correct `rule of thumb' is this:  if you find yourself writing
>
>   #.(create-something-from-a-printed-representation)
>
> all over the place, then you really could use a reader macro.

so would you only use read macros when building something at load
time? i'm assuming you would then _not_ use read macros to simplyify
"just" writing forms?

i ask because what i'd like to do is this:

#{a\b\c form} == (a (b (c form)))

-- 
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
     -Leonard Cohen
From: ·············@comcast.net
Subject: Re: per file messing with the read table
Date: 
Message-ID: <ism2lky9.fsf@comcast.net>
Marco Baringer <··@bese.it> writes:

> ·············@comcast.net writes:
>
>> Maybe the correct `rule of thumb' is this:  if you find yourself writing
>>
>>   #.(create-something-from-a-printed-representation)
>>
>> all over the place, then you really could use a reader macro.
>
> so would you only use read macros when building something at load
> time? i'm assuming you would then _not_ use read macros to simplyify
> "just" writing forms?
>
> i ask because what i'd like to do is this:
>
> #{a\b\c form} == (a (b (c form)))

My inclination would be not, but it depends.  Here's my rationale:

  - If I gave the code to someone else, they wouldn't immediately
    know that #{a\b\c form} is the same as (a (b (c form))), so
    you are increasing the intellectual burden.

    In the ITA example, however, since the problem domain is airports,
    people should grasp pretty quickly that #!BOS means Boston.

  - The form #{a\b\c form} isn't that much shorter than 
    (a (b (c form))), but #!BOS is a lot shorter than
     #.(string-to-tla "BOS")

  - It doesn't scale to binary functions.

  - If you were using a\b\c everywhere, you could abstract it:
    (defun a-b-c (x) (a (b (c x))))

That said, I can think of situations where you *would* want to make a
reader macro.  Suppose you were doing some sort of signal processing
where C was a function that acquired a signal from a source, B was a
filter, and A was some sort of `detector', and you were *constantly*
writing  

(defun edge-detect/smooth/from-ntsc (form)
   (edge-detect (smooth (from-ntsc form))))

(defun edge-detect/smooth/from-pal (form)
   (edge-detect (smooth (from-pal form))))

(defun edge-detect/clip/from-ntsc (form)
   (edge-detect (clip (from-ntsc form))))

(defun edge-detect/clip/from-pal (form)
   (edge-detect (clip (from-pal form))))

etc.

Then it might be clearer in your code to have 

  #{edge-detect\clip\from-ntsc (get-ntsc-source)}

so it is a judgement call.
From: Sebastian Stern
Subject: Re: per file messing with the read table
Date: 
Message-ID: <ad7d32de.0311030425.1dadf1b6@posting.google.com>
Marco Baringer wrote:
> i ask because what i'd like to do is this:
> 
> #{a\b\c form} == (a (b (c form)))

These two forms only differ in n+1 characters, where n is the number
of functions, and most of these characters are close parentheses,
which Lispers do not look at anyway, so this not much of an
improvement IMHO.

If you want to 'flatten' the function calls, you could use (funcall
(compose a b c) form) but this is more verbose than what you started
with. So then you  could define a reader macro <a b c> so that (<a b
c> form) reads as something like ((lambda (x) (funcall (compose a b c)
x)) form). One advantage of <a b c> above your reader macro is that is
reusable in other situations than the head of a form.

This is a good example of why Paul Graham thinks Lisp is too verbose.
You would not be tempted into using a reader-macro if the language was
just a little briefer. If the compose function could be just one
character, such as '.' and you had one namespace, you could write: ((.
a b c) form), which flattens the structure in the same way, and does
not require hacking the readtable.

Sebastian Stern
"Freedom is the freedom to say (= (+ 2 2) 4). If that is granted, all
else follows."
From: Kent M Pitman
Subject: Re: per file messing with the read table
Date: 
Message-ID: <wkptg78gdm.fsf@nospam.nhplace.com>
·············@comcast.net writes:

> Marco Baringer <··@bese.it> writes:
> 
> > I'd like to use a personal read macro and I want to make sure that any
> > changes I make to the readtable doesn't interfere with other code
> > (which will be LOADed seperatly from other files).
> >
> > I know that load rebinds *readtable* and my initial tests seem to say
> > that if the first thing I do in my file is:
> >
> > (eval-when (:compile-toplevel :load-toplevel :execute)
> >   (copy-readtable *readtable* *readtable*))

Almost.

I recommend doing this in a setup file:

 (defun my-readmacro1 ...)
 (defun my-readmacro2 ...)

 (defun setup-my-readmacro (&optional (readtable *readtable*))
   ... set up my-readmacro1, my-readmacro2, etc. on readtable ...
   readtable) ;return the modified readtable

 (defvar *my-readtable*
   (setup-my-readmacro (copy-readtable nil)))

Then later on a per-file basis:

 (in-package "MY-PACKAGE")
 (in-syntax *my-readtable*)

where IN-SYNTAX is just

 (defmacro in-syntax (readtable-expression)
   `(eval-when (:execute :load-toplevel :compile-toplevel)
      (setq *readtable* ,readtable-expression)))

(You'll note that the x3j13 cleanup proposal that gave you the fact
that *READTABLE* is bound by LOAD and COMPILE-FILE is called IN-SYNTAX.
This might give you a clue about what I originally had asked the 
committee for and what they bargained me down to.  Sigh...)

> > Then i can do whatever weird voodoo I want and the next file which
> > gets loaded will not see the changes.
> >
> > Is this correct?  Is there anything I should look out for? 
> 
> Here's what I do.  It's probably overkill for what you want, though.
> 
> I have a file that implements the reader for the funny syntax.
> It is compiled and loaded fairly early on, but it doesn't mess
> with the readtable.  It does this:
> 
>     (defvar *original-readtable* nil)
>     (defvar *special-readtable* nil)
> 
>     (defun enable-special-syntax ()
>       (setq *original-readtable* *readtable*
>             *readtable* (or *special-readtable* (copy-readtable)))
> 
>       (set-macro-character ...)
>       ...)
> 
>     (defun disable-special-syntax ()
>       (setq *readtable* *original-readtable*))

I don't recommend the above approach because *original-readtable* could be
set incompatibly by another process if LOAD is ongoing from two processes
at the same time.

The existing mechanisms are established correctly so that merely assigning
*READTABLE* will work correctly, with no need to "clean up" after.

> Then, in the file that uses the funny syntax, I write
> 
>     (eval-when (:compile-toplevel :load-toplevel :execute)
>       (enable-special-syntax))
> 
>     ;;; stuff with special syntax goes here
> 
>     (eval-when (:compile-toplevel :load-toplevel :execute)
>       (disable-special-syntax))
> 
> > Is this a "good" idea?
> 
> Tough question.  The answer is, `in general, don't mess with the
> readtable', but sometimes it is exactly the right thing.

I don't agree at all.

The only thing you shouldn't do is modify the initial readtable.

There is no harm in your making your own readtables and instantiating
them in 'bound' situations.  I do this a lot.

> At ITASoftware, a lot of hacking is done on TLAs (three letter
> acronyms).  Airports and cities all have canonical TLAs.  The obvious
> representation of a TLA as a string would be space and time
> inefficient, so there is a mapping from a TLA to a compact form.
> Instead of riddling the code with things like
>  #.(string-to-TLA "BOS"), I wrote a read macro so #!BOS would 
> read as the compact form.
> 
> On the configuration management project I'm working on, we hack a lot
> of distributed object identifiers.  These are structured objects, but
> they are interned.  Since they are used so frequently I hacked the
> reader such that [repository.object.24] was readable as distributed id.
> This saves a lot of this sort of stuff:
> 
>  #.(make-instance 'distributed-id :repository "repository"
>                                   :class 'object
>                                   :serial-number 24)
> 
> Maybe the correct `rule of thumb' is this:  if you find yourself writing
> 
>   #.(create-something-from-a-printed-representation)
> 
> all over the place, then you really could use a reader macro.

This is a good thing to have done but for other reasons than you cite.
It's good to avoid relying on #. because it's a security hole that
frequently needs to be turned off.  You don't want binding *read-eval*
to NIL to break the printer re-readability of your important objects,
so using your [...]  macro or whatever is a way of declaring that
these are "safe" to read even when *read-eval* is NIL.
From: Joe Marshall
Subject: Re: per file messing with the read table
Date: 
Message-ID: <znfayeaz.fsf@ccs.neu.edu>
Kent M Pitman <······@nospam.nhplace.com> writes:

> ·············@comcast.net writes:
>> Here's what I do.  It's probably overkill for what you want, though.
>> 
>> I have a file that implements the reader for the funny syntax.
>> It is compiled and loaded fairly early on, but it doesn't mess
>> with the readtable.  It does this:
>> 
>>     (defvar *original-readtable* nil)
>>     (defvar *special-readtable* nil)
>> 
>>     (defun enable-special-syntax ()
>>       (setq *original-readtable* *readtable*
>>             *readtable* (or *special-readtable* (copy-readtable)))
>> 
>>       (set-macro-character ...)
>>       ...)
>> 
>>     (defun disable-special-syntax ()
>>       (setq *readtable* *original-readtable*))
>
> I don't recommend the above approach because *original-readtable* could be
> set incompatibly by another process if LOAD is ongoing from two processes
> at the same time.
>
> The existing mechanisms are established correctly so that merely assigning
> *READTABLE* will work correctly, with no need to "clean up" after.

Unfortunately, I needed to do this to a small section of code, not the
whole file.

I also remember that in some circumstances it *wasn't* working
correctly and I'd end up with only some of my reader macros enabled.
There was some mess involving setting up read-macros without creating
a new readtable and another mess for attempting to set them back (it
was somebody else's code).  In any case, once I got the above solution
working I of course didn't pursue it further.

>> Then, in the file that uses the funny syntax, I write
>> 
>>     (eval-when (:compile-toplevel :load-toplevel :execute)
>>       (enable-special-syntax))
>> 
>>     ;;; stuff with special syntax goes here
>> 
>>     (eval-when (:compile-toplevel :load-toplevel :execute)
>>       (disable-special-syntax))
>> 
>> > Is this a "good" idea?
>> 
>> Tough question.  The answer is, `in general, don't mess with the
>> readtable', but sometimes it is exactly the right thing.
>
> I don't agree at all.
>
> The only thing you shouldn't do is modify the initial readtable.

Definitely.  The problem I was having was caused by someone trying
to temporarily alter the initial readtable and then set it back.

But the other thing you shouldn't do is modify a readtable that isn't
`yours'.

> There is no harm in your making your own readtables and instantiating
> them in 'bound' situations.  I do this a lot.

In `bound' situations, there's no harm, but I've encountered so many
cases of people doing it wrong, and for truly trivial purposes, that I
don't recommend doing it.
From: Kent M Pitman
Subject: Re: per file messing with the read table
Date: 
Message-ID: <wkoevqpuct.fsf@nhplace.com>
Joe Marshall <···@ccs.neu.edu> writes:

> > The existing mechanisms are established correctly so that merely assigning
> > *READTABLE* will work correctly, with no need to "clean up" after.
> 
> Unfortunately, I needed to do this to a small section of code, not the
> whole file.

Some people make a readmacro that sets up a smaller contour.
e.g.,

 #[*MY-READTABLE* ...stuff using *MY-READTABLE*]

> > The only thing you shouldn't do is modify the initial readtable.
> 
> Definitely.  The problem I was having was caused by someone trying
> to temporarily alter the initial readtable and then set it back.
> 
> But the other thing you shouldn't do is modify a readtable that isn't
> `yours'.

I guess I was thinking of this as a generalization of an "original
readtable".  That is, any readtable you didn't make that is accessible
to you was one that was made by someone else.  I didn't just mean
system readtables.  But we're in agreement, yes.

> > There is no harm in your making your own readtables and instantiating
> > them in 'bound' situations.  I do this a lot.
> 
> In `bound' situations, there's no harm, but I've encountered so many
> cases of people doing it wrong, and for truly trivial purposes, that I
> don't recommend doing it.

The cases that I think you have to do this are where there are pervasive
data structures with commonly understood summary notations.  URLs and
HTML/XML are the obvious web examples.  Things like Macsyma's infix 
notation for symbolic math expressions are another example of something 
that call for it, too.  I think people would get it right more often if
they didn't fear it and they practiced it some.  A LOT of concepts in
Lisp can be gotten wrong if you never use them, but a great many of them
become quite straightforward with practice--we put most of them there to
be used.