(define-syntax define-record (lambda (e) (syntax-case e () ((_ name field0 field1 ...) (with-syntax ((%fields (map (lambda (f) (syntax-case f () ((fname) (syntax (field fname #f))) ((fname default) (syntax (field fname default))) (fname (syntax (field fname #f))))) (syntax (field0 field1 ...))))) (syntax (define-record* name %fields))))))) (define-syntax define-record* (lambda (e) (letrec ((make-name (lambda args (datum->syntax e (string->symbol (apply string-append (map (lambda (a) (if (string? a) a (symbol->string (syntax->datum a)))) args))))))) (syntax-case e (field) ((_ name ((field field-name default) ...)) #`(begin (define* (#,(make-name "make-" (syntax name)) #:optional (field-name default) ...) (vector 'name field-name ...)) #,@(let ((idx 0)) (map (lambda (fname) (set! idx (1+ idx)) #`(begin (define (#,(make-name (syntax name) ":" fname) rec) (vector-ref rec #,idx)) (define (#,(make-name "set-" (syntax name) ":" fname) rec val) (vector-set! rec #,idx val)))) (syntax (field-name ...))))))))))