Macros 如何使用Racket宏定义函数?

Macros 如何使用Racket宏定义函数?,macros,scheme,racket,Macros,Scheme,Racket,我正在尝试编写一个宏,它定义了一类特殊的数据结构和相关函数 我知道这是可能的;它在核心语言本身中执行了多次 作为一个具体示例,我将如何在Scheme本身中定义define struct宏。它需要创建make struct,struct-等函数 我尝试使用define,但是,这只定义宏词法范围中的函数 如何在宏中定义函数?答案的关键是datum->syntax。基本思想是,您希望获取一些随机数据并将其转换为语法——在本例中,将符号转换为标识符。标识符基本上是一个符号,带有一些词汇信息(非常粗略地)

我正在尝试编写一个宏,它定义了一类特殊的数据结构和相关函数

我知道这是可能的;它在核心语言本身中执行了多次

作为一个具体示例,我将如何在Scheme本身中定义
define struct
宏。它需要创建
make struct
struct-
等函数

我尝试使用
define
,但是,这只定义宏词法范围中的函数


如何在宏中定义函数?

答案的关键是
datum->syntax
。基本思想是,您希望获取一些随机数据并将其转换为语法——在本例中,将符号转换为标识符。标识符基本上是一个符号,带有一些词汇信息(非常粗略地)指示其绑定方式。使用
datum->syntax
就可以做到这一点:它需要一个现有的语法片段(它从中复制绑定),以及一个数据(这里是一个符号),它是语法包装中包含的值

下面是一个示例,演示了一个类似于定义结构的工具,该工具使用以下内容:

#lang scheme
;; implements a defstruct-like macro that uses association lists
(define-syntax (defstruct-lite stx)
  (syntax-case stx ()
    [(defstruct-lite name field ...)
     (let ([make-id
            (lambda (template . ids)
              (let ([str (apply format template (map syntax->datum ids))])
                (datum->syntax stx (string->symbol str))))])
       (with-syntax ([make-name (make-id "make-~a" #'name)]
                     [name?     (make-id "~a?" #'name)]
                     [(arg ...) (generate-temporaries #'(field ...))]
                     [(name-field ...)
                      (map (lambda (f) (make-id "~a-~a" #'name f))
                           (syntax->list #'(field ...)))])
         #'(begin
             (define (make-name arg ...) (list 'name (cons 'field arg) ...))
             (define (name? x) (and (pair? x) (eq? 'name (car x))))
             (define (name-field x)
               (and (name? x) (cdr (assq 'field (cdr x)))))
             ...)))]))
下面是一个使用它的示例:

(defstruct-lite point x y)
(point-y (make-point 1 2))