Your `syntax-rules` macro-defined macro uses the name "b", but that name is already bound by the `syntax-case` step of `define-primitive`. So your expansion looks like this:
(define-primitive (add a b c d) (print (+ a b c d))) => (begin (define add-property-table (make-hash)) (hash-set! add-property-table 'is-prime #t) (hash-set! add-property-table 'arg-count (length '(a b c d))) (hash-set! add-property-table 'emitter (lambda (a b c d) (print (+ a b c d))) (define-syntax add (syntax-rules () ((add a) (list 'add a)) ((add a (print (+ a b c d))) (list 'add a (print (+ a b c d))))))) Note that `add` macro you create uses `(print (+ a b c d))` instead of `b` in the second pattern. You can rectify this by using a different name. However, here are a couple other notes to consider: - `syntax-case` is considered somewhat obsolete in the Racket community, `syntax-parse` allows for better-specified patterns and error messages. Your example with syntax parse would look like (synatx-parse stx [(_ (primitive-name arg*:id ...) b:expr ...+) <macro body here>]). This makes your macro throw a syntax error if anything used for `arg*` isn't an identifier, or if non-expression syntax (like a keyword) is used for `b`. - Construction of the "-property-table" identifier can be done much more concisely with `format-id`, making your DS/SS/SD shorthands unnecessary - Avoid mutable data structures unless you know you need mutation. Your `hash-set!` code can be easily expressed with a plain call to `hash`: (define table-name (hash 'is-prime #t 'arg-count (length '(a b c d)) 'emitter (lambda (a b c d) (print (+ a b c d))))) - When a macro defines a macro, the elipses (...) refer to the outer macro template. This is why you couldn't use ... in the `syntax-rules` macro you attempted to create. You can get around this by using two ellipses grouped together, like this: (define-syntax primitive-name (syntax-rules () ((primitive-name a (... ...)) (list 'primitive-name a (... ...))))) - It's considered good Racket style to use brackets for the clauses of `syntax-rules` / `syntax-case` / `syntax-parse`, like this: (syntax-case stx () [(pattern ...) body ...] [(pattern ...) body ...])) - If you (require syntax/parse/define) you can use `define-simple-macro` (badly named, we know) in place of `define-syntax-rule`. They function similarly, but the former uses `syntax/parse` and thus lets you specify constraints like "this should be an identifier". - The macro you create for each primitive is exactly the same. It may be simpler to factor that out into a separate macro: (define-simple-macro (define-primitive-application-syntax (primitive-name:id arg:id ...)) (define-simple-macro (primitive-name arg-expr:expr (... ...)) (list 'primitive-name arg-expr ...))) (define-syntax (define-primitive stx) (syntax-parse stx () [(_ (primitive-name:id arg:id ...) body ...+) #:with table-name (format-id #'primitive-name "~a-property-table" #'primitive-name) #'(begin (define table-name <hash-expr-mentioned-previously>) (define-primitive-application-syntax (primitive-name arg ...))])) Hope this helps! -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.