[racket-dev] with-syntax and #:with are not compatible

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Mon Sep 30 21:25:39 EDT 2013

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

Posted on the dev mailing list.