Thank you so much Jack,

This certainly helps! I was following the tutorial
http://www.greghendershott.com/fear-of-macros/ - It turns out that it too
recommends syntax-parse at the very end :)

When I tried this, I got "syntax: no pattern variables before ellipsis in
template in: ..."

(require syntax/parse/define)


(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 ...))) ; ERROR here

(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 'is-prime #t
        'arg-count (length '(arg ...))
        'emitter (lambda (arg ...) body ...))))

        (define-primitive-application-syntax (primitive-name arg ...))]))




Regards,
Kashyap

On Wed, Sep 21, 2016 at 2:05 PM, Jack Firth <[email protected]> wrote:

> 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 [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to