【问题标题】:How do I define functions using Racket macros?如何使用 Racket 宏定义函数?
【发布时间】:2011-02-22 20:18:42
【问题描述】:

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

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

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

我尝试使用define 执行此操作,但是,这仅在宏的词法范围内定义函数。

如何在宏中实际定义函数?

【问题讨论】:

标签: macros scheme racket


【解决方案1】:

答案的关键是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)))))
             ...)))]))

下面是一个使用它的例子:

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

【讨论】:

    猜你喜欢
    • 2014-12-23
    • 2017-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多