2010-05-23 24 views
8

Estoy tratando de escribir una macro que define una clase especial de estructura de datos con funciones asociadas.¿Cómo defino funciones usando macros Racket?

Sé que esto es posible; se realiza varias veces en el lenguaje central en sí.

Como ejemplo específico, ¿cómo definiría la macro define-struct en el propio Scheme. Necesita crear las funciones make-struct, struct-<<field>>, etc.

Intenté hacer esto usando define, sin embargo, esto solo define la función en el alcance léxico de la macro.

¿Cómo puedo definir una función en una macro?

+1

http://www.scheme.com/tspl4/ examples.html #./examples: h8 – grettke

Respuesta

16

La clave para una respuesta es datum->syntax. La idea básica es que desee tomar algunos datos aleatorios y convertirlos en una sintaxis, en este caso, convertir un símbolo en un identificador. Un identificador es básicamente un símbolo con cierta información léxica que (muy aproximadamente) indica cómo está vinculado. Usando datum->syntax puede hacer exactamente eso: espera una pieza de sintaxis existente que es donde copia el enlace desde, y un dato (un símbolo aquí) que es el valor que está contenido en el contenedor de sintaxis.

Aquí hay un ejemplo que demuestra una herramienta define-struct -como el uso de este:

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

Y aquí es un ejemplo de su uso:

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

http://www.scheme.com/tspl4/examples.html#./examples:h8 – grettke

Cuestiones relacionadas