[plt-scheme] attempt to discern applications from syntactic forms fails

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Thu Jan 15 12:57:00 EST 2009

At Thu, 15 Jan 2009 18:40:36 +0100, "Jos Koot" wrote:
> My question is at the <===== in the following code:
> (define-syntax (x stx)
>  (syntax-case stx ()
>   ((_ x)
>    (let ((y (expand-once #'x)))
>     (printf "~s~n" (syntax->datum y))
>     (syntax-case y (#%app)
>      ((#%app . z) #''app)
>      (_ #''no-app))))))
> [...]
> (x (list 1 2 3))
> ; printed (#%app list 1 2 3)
> ; value: no-app, why??? <===== I expected app

The `expand-once' is working at phase 1, while `syntax-case' is
comparing identifiers at phase 0.

Furthermore, the `#%app' of `scheme/base' is being expanded to
`#%plain-app'. Confusingly, in the scope of the `#%app' definition,
`#%plain-app' is called `#%app', so the expansion prints as `#%app'

So, you would have gotten the expected results with

    (syntax-case* y (#%plain-app) free-transformer-identifier=?
     ((#%plain-app . z) #''app)
     (_ #''no-app))

I doubt that this is what you really intended, though. I think it's
more likely that you wanted to use `local-expand' (which will expand
the given expression at phase 0) and use `#%app' as one of the stop
forms, in which case the `syntax-case' match would work as you expect.

Actually, depending on the context, it's probably better to use
`#%plain-app' as a stop form, in which case you'll match on
`#%plain-app'. That works with macros defined in a language other than
`scheme/base', since `#%plain-app' is the primitive application form.


Posted on the users mailing list.