2010-05-23 33 views
8

我想写一个宏,它定义了一个具有关联函数的特殊类数据结构。如何使用球拍宏定义功能?

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

作为一个具体的例子,我将如何在Scheme中定义define-struct宏。它需要创建make-structstruct-<<field>>等功能。

我试着用define这样做,但是,这只是在宏的词法范围中定义函数。

我怎样才能在宏中定义一个函数?

+1

http://www.scheme.com/tspl4/ examples.html#。/ examples:h8 – grettke 2010-05-23 13:14:00

回答

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))))) 
      ...)))])) 

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

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

http://www.scheme.com/tspl4/examples.html#./examples:h8 – grettke 2010-06-08 13:46:01