简体   繁体   中英

How do defines and syntax macros interact in Racket?

I'm new to Racket and there's something about syntax macros I don't understand. I have these two programs:

This one, which executes correctly:

#lang racket

(define-syntax-rule (create name) (define name 2))

(create x)

(displayln (+ x 3))

And this one, which complains that the identifier x is unbound:

#lang racket

(define-syntax-rule (create) (define x 2))

(create)

(displayln (+ x 3))

With a naive substitution approach (such as C/C++ macros) these two programs would behave identically, but evidently they do not. It seems that identifiers that appear in the invocation of a syntax macro are somehow "special" and define s that use them behave differently to define s that do not. Additionally, there is the struct syntax macro in the Racket standard library which defines several variables that are not explicitly named in its invocation, for example:

(struct employee (first-name last-name))

Will define employee? and employee-first-name , neither of which were directly named in the invocation.

What is going on here, and it can be worked around so that I could create a custom version of struct ?

The problem with the naive substitution is unintentional capturing. Racket macros by default are hygienic, which means it avoid this problem. See https://en.wikipedia.org/wiki/Hygienic_macro for more details.

That being said, the macro system supports unhygienic macros too. struct is an example of an unhygienic macro. But you need to put a bit more effort to get unhygienic macros working.

For example, your second version of create could be written as follows:

#lang racket

(require syntax/parse/define)

(define-syntax-parse-rule (create) 
  #:with x (datum->syntax this-syntax 'x)
  (define x 2))

(create)

(displayln (+ x 3))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM