nic*_*ame 8 macros scheme racket
我正在尝试编写一个宏来定义具有相关函数的特殊数据结构类.
我知道这是可能的; 它在核心语言本身中多次完成.
作为一个具体的例子,我如何define-struct在Scheme本身中定义宏.它需要创造make-struct,struct-<<field>>等功能.
我试过这样做define,但是,这只定义了宏的词法范围中的函数.
如何在宏中实际定义函数?
Eli*_*lay 16
答案的关键是datum->syntax.基本思想是你想要获取一些随机数据并将其转换为语法 - 在这种情况下,将符号转换为标识符.标识符基本上是带有一些词法信息的符号(非常粗略地)表示它是如何绑定的.使用datum->syntax你可以做到这一点:它需要一个现有的语法,它复制绑定,以及一个数据(这里是一个符号),它是语法包装器中包含的值.
这是一个演示define-struct使用它的类似工具的示例:
#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)))))
...)))]))
Run Code Online (Sandbox Code Playgroud)
这是一个使用它的例子:
(defstruct-lite point x y)
(point-y (make-point 1 2))
Run Code Online (Sandbox Code Playgroud)