[plt-scheme] identifier macros in application position
David A. Herman writes:
> Why doesn't the following work?
>
> ;; add1*: add1 with constant folding
> (define-syntax (add1* stx)
> (syntax-case stx ()
> [(add1* n)
> (number? (syntax-object->datum #'n))
> (datum->syntax-object stx (add1 (syntax-object->datum #'n)))]
> [add1*
> (identifier? #'add1*)
> #'add1]))
>
> (add1* (+ 2 3))
>
> The expression fails to match, which surprised me. Apparently identifier
> macros only match in operand position. Why is that?
It matches in operator position too, but in that case the value of
`stx' is the entire expression, not just the identifier:
The transformer for an identifier is applied whenever the identifier
appears in an expression position -- not just when it appears after
a parenthesis as `(identifier ...)'. When it does appear as
`(identifier ...)', the entire `(identifier ...)' expression is
provided as the argument to the transformer. Otherwise only
`identifier' is provided to the transformer.
There's no such thing as an "identifier macro"-- all macros are just
identifiers bound to syntax transformers. Maybe you're being confused
by the difference between `syntax-rules' and `syntax-id-rules'?
(which is irrelevant if you're using `syntax-case')
> On the one hand, this
> makes it easy to tell what position the macro is being used in, but on the
> other hand, if identifier macros matched in any context, you could still
> distinguish the position by capturing all application contexts in the
> first patterns followed by the identifier macro, e.g.:
>
> (define-syntax (foo stx)
> (syntax-case stx ()
> [ ... special cases ... ]
> [(foo . anything)
> ... default case for application position ... ]
> [foo
> (identifier? #'foo)
> ... operand position case ...]))
This works already:
> (define-syntax (add1* stx)
(syntax-case stx ()
[(add1* n)
(number? (syntax-object->datum #'n))
(datum->syntax-object stx (add1 (syntax-object->datum #'n)))]
[(add1* . anything)
#'(add1 . anything)] ;; default case for operator position
[add1*
(identifier? #'add1*)
#'add1]))
> (add1* (+ 2 3))
6
Or am I misunderstanding your question?
--dougo at place.org
P.S. Since you have an explicit `identifier?' guard, the third case
could appear anywhere-- it doesn't have to be last. Alternatively,
if it's last, you don't need the `identifier?' guard, except as a
defensive programming tactic.