[racket-dev] with-syntax and #:with are not compatible
The following program errors:
#lang racket/base
(require (for-syntax racket/base
syntax/parse))
(define-syntax (a1 stx)
(syntax-parse stx
[(_ b)
(with-syntax ([x 5])
#'(+ b x))]))
(a1 7)
(define-syntax (a2 stx)
(syntax-parse stx
[(_ b)
#:with x 5
#'(+ b x)]))
(a2 7)
The cause is that with-syntax has the following behavior:
" if any individual stx-expr produces a non-syntax object, then it is
converted to one using datum->syntax and the lexical context and
source location of the individual stx-expr."
meaning that inside of with-syntax there is something like (datum->syntax #'5 5)
In contrast, #:with does not document what it does in this situation,
merely that
"If the value of stx-expr is not a syntax object, it is implicitly
converted to a syntax object."
If we look at the implementation, L182 of syntax/parse/private/residual we see:
(datum->syntax #f x #f)
However, I do not believe it is enough to change this too something like
(datum->syntax x x #f)
Because calls such as L684 in syntax/parse/private/parse do not bind x
to the user's code, but to something from the implementation of syntax
parse.
I believe this inconsistency between #:with and with-syntax is an
error and should be fixed, but I do not feel that I understand all the
ways to flow to this code, so I implore Ryan to change it.
Jay
--
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay
"The glory of God is Intelligence" - D&C 93