[racket] Macro defining functions question

From: Kevin Forchione (lysseus at gmail.com)
Date: Thu May 15 12:32:03 EDT 2014

This one leaves me scratching my head. Why doesn’t this work? When you run the macro the functions aren’t defined outside of the extent of the begin.

(define-syntax (foo stx)
  (syntax-case stx ()
    [(foo)
     #'(begin
         (define (bar x) x)
         (define (baz x) x))]))

After inning the macro (bar 3) produces an bar undefined error. 

On the other hand, this works:

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

In the 2nd example, once you run the macro you can then use the make- functions to define points. 




Posted on the users mailing list.