From: Jeff M.
Subject: Modifying the reader at compile-time
Date: 
Message-ID: <ci50d9$30f@odak26.prod.google.com>
I was wondering if there was any way for me to modify the read-table at
compile time with a macro /before/ the arguments to the macro were
evaluated. For example, which I know completely fails, but hopefully
gets the idea across:

(defun foo (char stream) (bar))

(defmacro special-macro (symbol foo-result)
(set-macro-character #\{ #'foo)
`(setf ,symbol ,foo-result)
(set-macro-character #\{ nil))

(special-macro x { blah })


The reasoning here is that I don't want the syntax for { to be
available outside of the special-macro macro. Any advice welcome and
appreciated!

Jeff
P.S. Sorry for the lack of indentation; Google doesn't seem to like it.

From: Joel Ray Holveck
Subject: Re: Modifying the reader at compile-time
Date: 
Message-ID: <y7c4qm1q2rc.fsf@sindri.juniper.net>
> I was wondering if there was any way for me to modify the read-table at
> compile time with a macro /before/ the arguments to the macro were
> evaluated.

Let me restate your example, to make sure I understand you correctly.

(defmacro mymac (&rest args)
  ;; Funky macro that does what you're talking about
  ,(,(dwim)))

;; Later, possibly in another file...
(mymac { foobar } { bazquux })

where the {...} read syntax is set up by mymac, to only exist the
lexical scope of the mymac call.

The problem is not when the arguments to the macro are evaluated, but
rather when they're read.  The Lisp interpreter must be able to read
the arguments before it can pass them to mymac.

Suppose that I defined a macro character [ that reads a string, ended
by a matching ], and nested []s are handled correctly.  Then I write: 
  (mymac [ foobar } [ bazquux })]])

Now, mymac is called with a single argument.  But suppose that I make
[ read until it sees a } (note: different character!) instead, and ]
is a comment marker.  Now mymac is called with two arguments.

So the basic answer seems to be, no, a macro can't define how its
arguments will be read, since it's not called until the read is
complete.

You could do something like this, however:
  (#mymac { foobar } { bazquux } )
and define #m as a macro character that reads however you want it to.

For example, you could have it unread the "m", read a symbol, and look
that symbol up in a dispatch table.  The dispatch table contains a
macro dispatch function, and an altered readtable.  It then reads a
delimited list using the altered readtable, until it encounters the ),
and calls the dispatch function.  This wouldn't work with your example
name SPECIAL-MACRO, since #S is already a macro character, so you may
be better off using a syntax like (#!mymac ...) instead.

You could get pretty elaborate if you want to and make a general
facility for this.  I personally wouldn't, but you're free to.

Note that, by doing this, you're effectively making whatever it is
that {...} reads no longer a first-class object, since your users have
no way to create one (assuming you don't also have a constructor
function).  In general, I find that Lisp's beauty is by giving users
lots of tools that most languages leave under the hood, such as
first-class functions and the MOP.  I try to write my programs in the
same spirit.  But that's just my general opinion, and you're free to
write the program however you want.

Cheers,
joelh
From: Peter Seibel
Subject: Re: Modifying the reader at compile-time
Date: 
Message-ID: <m3d60p6g8f.fsf@javamonkey.com>
"Jeff M." <·······@gmail.com> writes:

> I was wondering if there was any way for me to modify the read-table
> at compile time with a macro /before/ the arguments to the macro
> were evaluated. 

You can change the read-table before the macro's arguments are
*evaluated*. But you seem rather to want to modify the read-table
before the macro's arguments are *read*, which you can't do from
within the macro. That is, the whole macro form has been read and
turned into objects before the macro expander runs. So modifying the
read-table within the macro expander won't have any affect.

-Peter

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

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Kaz Kylheku
Subject: Re: Modifying the reader at compile-time
Date: 
Message-ID: <cf333042.0409171701.162f139e@posting.google.com>
"Jeff M." <·······@gmail.com> wrote in message news:<··········@odak26.prod.google.com>...
> I was wondering if there was any way for me to modify the read-table at
> compile time with a macro /before/ the arguments to the macro were
> evaluated. For example, which I know completely fails, but hopefully
> gets the idea across:

At compile time, everything has already been read, so it's too late to
fiddle with the reader.

> The reasoning here is that I don't want the syntax for { to be
> available outside of the special-macro macro. Any advice welcome and
> appreciated!

The architecture of Lisp does not support the idea of lexically scoped
read syntax. A top-level form is read in its entirety before it is
further processed (compiled or evaluated). Reading and evaluation are
separate layers that do not communicate. (Of course, evaluation of a
from can alter the read table so that the reading of other forms is
affected, but that form itself has already been read so it's too
late).

Any kind of special trick for context-sensitive enabling/disabling of
special read syntax has to be done entirely using the reader, under
the control of a read macro that is invoked to process the entire
form. That read macro will have to analyze the input sufficiently
deeply to understand where to support the { syntax and where not.