[plt-scheme] #%app literal does not match in syntax-case pattern

From: Eli Barzilay (eli at barzilay.org)
Date: Fri Nov 20 00:15:40 EST 2009

On Nov 19, Marco Monteiro wrote:
> Hello.
> 
> I have this reader in pltcollects/masm/lang/reader.ss
> 
> -------
> (module reader syntax/module-reader
> [...]
>   )

I didn't actually read your code, but I think that I see your general
problem.  Roughly speaking, the best (or the sanest) rule of thumb to
follow is for the reader module to not do anything beyond reading raw
syntax.  For example, even something like

  (define (my-reader ...)
    ... #'(+ 1 2) ...)

would be wrong because it plants a piece of syntax with a lexical
context that comes from the reader module itself.  Instead, this
should be:

  (define (my-reader ...)
    ... (datum->syntax #f '(+ 1 2) ...) ...)

which creates such a raw piece of syntax.  If you follow this line,
then you'll see why uses of `expand' in the reader module (or any need
for making a namespace) are bad: they mix the two levels of the reader
and macro expansion.  It's basically the same as mixing evaluation
with reading.

Note that I'm not saying that what you're trying to do is impossible
(to say that, I'll need to at least read and understand what you're
trying to do) -- just that there's some problems that are inherent to
that approach.  For example, it might be possible to first expand the
syntax, then turn it back into context-less syntax (eg, by expanding
it, then turning the result into a datum, and then turning that back
into a syntax using #f as above, and finally matching on plain symbols
in your post-processing step).

But my first thought when I saw that (or rather when someone pointed
at your question when you raised it on #scheme) is that you're trying
to do some CL-ish kind of a code walker.  (And I did see that you
mentioned that this is a translation of CL code, so it seems
relevant.)  In this case, I think that trying to *match* on `#%app's
is missing its point.  The role of `#%app' is as a kind of a hook that
you can use to redefine what happens on every point where a function
is being applied *instead* of using a code walker.

For example, say that I want to have a language where the four
arithmetic operators can be used in infix form (ignoring issues that
the result from the ambiguity in doing that).  The CL approach would
be to write a macro that implements a code walker whose job is to
identify sexprs that stand for function application, and then
transforming those where you see any of these operators in an infix
position.  (And I'm also ignoring the lack of real identifiers in CL
for this example.)

In PLT, you can use `#%app' instead of a code walker, and it gets to
do its work wherever a function application is happening -- which
frees you from the huge hassle involved in a code walker.  In this
case, I can do this easily with:

  ;; "infix.ss"
  #lang scheme/base
  (provide (except-out (all-from-out scheme/base) #%app)
           (rename-out [my-app #%app]))
  (define-syntax my-app
    (syntax-rules (+ - * /)
      [(_ x + y) (+ x y)]
      [(_ x - y) (- x y)]
      [(_ x * y) (* x y)]
      [(_ x / y) (/ x y)]
      [(_ f x ...) (f x ...)]))

And then:

  #lang s-exp "infix.ss"
  (define (fib n)
    (if (<= n 1) n ((fib (n - 1)) + (fib (n - 2)))))

As a side bonus of using PLT, you also get this to work even when the
identifiers are renamed:

  ;; "infix.ss"
  #lang scheme/base
  (provide (except-out (all-from-out scheme/base) #%app)
           (rename-out [my-app #%app])
           (rename-out [+ plus] [- minus]))
  (define-syntax my-app
    (syntax-rules (+ - * /)
      [(_ x + y) (+ x y)]
      [(_ x - y) (- x y)]
      [(_ x * y) (* x y)]
      [(_ x / y) (/ x y)]
      [(_ f x ...) (f x ...)]))

  #lang s-exp "infix.ss"
  (define (fib n)
    (if (<= n 1) n ((fib (n minus 1)) plus (fib (n minus 2)))))

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!


Posted on the users mailing list.