[racket] define-syntax-class

From: Nadeem Abdul Hamid (nadeem at acm.org)
Date: Wed Apr 27 23:52:34 EDT 2011

On Wed, Apr 27, 2011 at 11:25 PM, Carl Eastlund <cce at ccs.neu.edu> wrote:
> Modules currently can't define syntax for syntax.  However, you can
> use define-syntax-set from mzlib/etc to define multiple macros at once
> that share local bindings, such as syntax classes.  Since they're
> lexical bindings rather than module bindings, they work just fine.  If
> you want to export them and share them between files, however, you'll
> need to use Sam's suggestion.

That's what I was looking for. Thank you. Here's a complete example
for posterity:

#lang racket/base

(require syntax/parse mzlib/etc
         (for-syntax syntax/parse

(define-syntax-set (let let1)

  (define-syntax-class binding
    #:description "binding pair"
    (pattern [var:identifier rhs:expr]))

  (define-syntax-class distinct-bindings
    #:description "sequence of binding pairs"
    (pattern (b:binding ...)
             #:with (var ...) #'(b.var ...)
             #:with (rhs ...) #'(b.rhs ...)
             #:fail-when (check-duplicate-identifier (syntax->list #'(var ...)))
             "duplicate variable name"

  (define (let/proc stx)
    (syntax-parse stx
       [(let bs:distinct-bindings body:expr)
        #'((λ (bs.var ...) body) bs.rhs ...)]
        (raise-syntax-error #f
                            "expected a sequence of binding pairs and
a body expression"
                            stx #'let)]

  (define (let1/proc stx)
    (syntax-parse stx
       [(let1 b:binding body:expr)
        #'((λ (b.var) body) b.rhs)]
        (raise-syntax-error #f
                            "expected a binding pair and a body expression"
                            stx #'let1)]

(let ([x 1] [y 2]) (+ x y))
(let ((x 4)) (sub1 x))
(let1 (y 2) (add1 y))

All cause errors:
(let x (add1 x))
(let ([x 1]) )
(let ([x 1] [x 2]) (+ x x))
(let ([(x) (f 7)]) (g x x))
(let ([x 1] [y 2]) (+ x x) 4)

Posted on the users mailing list.