unbound variable in racket macro
I am testing a wrapper macro around the racket syntax-case
macro. At step 1, it does nothing interesting and simply passes through all the parts to syntax-case
directly as follows:
#lang racket
;; definition
(define-syntax guarded-syntax-case
(lambda (x)
(syntax-case x ()
((guarded-syntax-case y (literal ...) clause ...)
#'(syntax-case y (literal ...) clause ...)
))))
;; test case
(define-syntax (binop stx)
(guarded-syntax-case stx () ; *problem site*
[(_ op n1 n2) #'(op n1 n2)]))
But this simple case fails with the following error at the empty brackets ()
labeled with problem site labeled in above code:
; ....rkt:11:27: #%app: missing procedure expression;
; probably originally (), which is an illegal empty application
; after encountering unbound identifier (which is possibly the real problem):
; guarded-syntax-case
; in: (#%app)
I couldn't figure out what could be wrong in this simple pass-through macro. The error message开发者_JAVA百科 seems to suggest that there is a unbound variable somewhere, which I couldn't identify. I would think that the literal ...
should be matched to empty.
Could someone help explain what went wrong and how to fix the macro?
The problem is that guarded-syntax-case
is not recognized as a macro in the correct phase. In particular, when you (define-syntax guarded-syntax-case ...)
in your program, you define the macro guarded-syntax-case
that is available in phase 0. But forms in (define-syntax (binop stx) ...)
must be in phase 1.
There are two ways to correct the mistake.
- You can wrap
(define-syntax guarded-syntax-case ...)
insidebegin-for-syntax
. However, doing so would requiresyntax-case
and other stuff to be available in phase 2. So you need an additional(require (for-meta 2 racket/base))
. Here's the full code:
#lang racket
(require (for-meta 2 racket/base))
;; definition
(begin-for-syntax
(define-syntax guarded-syntax-case
(lambda (x)
(syntax-case x ()
((guarded-syntax-case y (literal ...) clause ...)
#'(syntax-case y (literal ...) clause ...))))))
;; test case
(define-syntax (binop stx)
(guarded-syntax-case stx () ; *problem site*
[(_ op n1 n2) #'(op n1 n2)]))
(binop + 1 2) ;=> 3
- Alternatively, you can define a (sub)module that provides
guarded-syntax-case
, and thenrequire
the (sub)module withfor-syntax
. Here's the full code:
#lang racket
(module lib racket
(provide guarded-syntax-case)
;; definition
(define-syntax guarded-syntax-case
(lambda (x)
(syntax-case x ()
((guarded-syntax-case y (literal ...) clause ...)
#'(syntax-case y (literal ...) clause ...))))))
(require (for-syntax 'lib))
;; test case
(define-syntax (binop stx)
(guarded-syntax-case stx () ; *problem site*
[(_ op n1 n2) #'(op n1 n2)]))
(binop + 1 2)
精彩评论