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 <jackhfi...@gmail.com> 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 racket-users+unsubscr...@googlegroups.com.
> 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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to