开发者

unbound variable in racket macro

开发者 https://www.devze.com 2022-12-07 22:21 出处:网络
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:

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.

  1. You can wrap (define-syntax guarded-syntax-case ...) inside begin-for-syntax. However, doing so would require syntax-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
  1. Alternatively, you can define a (sub)module that provides guarded-syntax-case, and then require the (sub)module with for-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)
0

精彩评论

暂无评论...
验证码 换一张
取 消