[plt-scheme] Understanding readtables
A few relevant notes:
On Jul 4, Mark Engelberg wrote:
>
> [...]
>
> Okay, now he's created a custom write function that displays a bundle
> as #*((+ 1 2) . 3)
>
> He wants to customize the reader so that he can read back in this
> printed version of the bundle, sort of like #(1 2 3) for making
> vectors, or #hash((1 . 2)) for making a hash table. He ideally
> envisions that the reader would handle either #*((+ 1 2) . 3) or
> #*((+ 1 2)) and it will return #*((+ 1 2) . 3)
What about #*((+ 1 2) . 5) ?
Also, it's wrong to think of it as "returning" a value. Better to
think of it as what it translates to as a new piece of syntax. For
example, make #*(<X> . <Y>) translate to (bundle <X> <Y>), which has
an implication if you put it inside quote, for example. (And in an
answer to the above, I imagine `bundle' with a second argument testing
that value and throwing an error if it's wrong.)
The reason for this is that otherwise you get into problems with
evaluating an expression at read-time, which is usually going to be a
bad idea. For example, you probably want this to work:
(let ([x 1])
#*((+ x 2) . 3))
> So from the documentation, it sounds like he needs to extend the
> readtable with a dispatch-macro, that calls a special reading
> function that will be called when the reader is called for #*.
> Something like:
>
> (current-readtable (make-readtable (current-readtable) #\*
> 'dispatch-macro readerbundle))
>
> But this doesn't quite work, and it's not really clear what form
> this reader function needs to take. Can someone set us on the right
> path here?
You can look in collects/scribble/reader.ss for an example. You
generally want a function that gets
char - the character that was used to call this function
inp - the input port
source-name line-num col-num position - location information
and returns a piece of syntax.
Important things to remember:
* The syntax is best built with
(datum->syntax #f <s-expression>
(vector ...location-info...)
[orig-stx])
the first thing should be #f -- so you produce a syntax with no
lexical information (that will be problematic since if you do that
then it'll be the lexical context of the reader code that generated
it or something similar).
* Changing the readtable with (current-readtable <foo>) is not a good
idea since it's a side-effect, is use it only for testing. Later
on, it's best to write a module that provide `read' and
`read-syntax' and use it with something like
#reader "my-reader.ss"
and these functions will use `parameterize' to have a local change
of the syntax only. scribble/reader.ss has an example of that also
(at the bottom of the file).
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://www.barzilay.org/ Maze is Life!