[racket] ... in macro defining macros?

From: Jon Rafkind (rafkind at cs.utah.edu)
Date: Fri Aug 3 02:55:17 EDT 2012

To match a literal ellipses in syntax-parse use #:literal [(ellipses ...)] and match on the term `ellipses', then to use a literal ellipses in the template use (... ...) instead of just ...

It looks like you only want the latter, so

(define-syntax (example stx)
  (syntax-parse stx
    [(_ name:id) #'(define-syntax (name stx)
                              (syntax-parse stx
                                 [(_ args (... ...)) #'(args (... ...)))])]))

On 08/02/2012 11:30 PM, Nick Sivo wrote:
> Hi,
>
> I'm trying to use ... in the inner macro of a macro defining macro,
> but can't figure out the right way to escape it.
>
> Here's a minimal (pointless) example:
>
> (require (for-syntax syntax/parse))
>
> (define-syntax (example stx)
>   (syntax-parse
>    stx
>    ;#:literals (...) ; Doesn't help :(
>    [(_ name:id)
>     #'(define-syntax (name stx)
>         (syntax-parse
>          stx
>          [(_ args ...) #'(args ...)]))]))
>
> The goal is to have (example invisible) define a macro called
> invisible that erases itself.
>
> Any ideas?  The full code I'm trying to enable follows below if you'd
> like more context.
>
> Thanks,
> Nick
>
> #lang racket
>
> (require (for-syntax syntax/parse)
>          racket/splicing)
>
> ;;;
> ;;; Procedure Application
> ;;;
>
> (define arc-nil #f)
>
> (define-syntax (arc-#%app stx)
>   (syntax-parse
>    stx
>    [(_ fn:expr arg:expr)
>     #'(let ([efn fn])
>         (cond [(procedure? efn) (#%app efn arg)]
>               [(pair? efn) (#%app list-ref efn arg)]
>               [(string? efn) (#%app string-ref efn arg)]
>               [(hash? efn) (#%app hash-ref efn arg arc-nil)]
>               [else (#%app efn arg)]))]
>    [(_ fn:expr arg1:expr arg2:expr)
>     #'(let ([efn fn])
>         (if (hash? efn)
>             ; Have to use the lamda in case arg2 is a function
>             ; See hash-ref docs for more info
>             (#%app hash-ref fn arg1 (lambda () arg2))
>             (#%app fn arg1 arg2)))]
>    [(_ args ...)
>     #'(#%app args ...)]))
>
> ; This allows cross module mutation of globals
> (define-syntax (declare-with-set-transformer stx)
>   (syntax-parse
>    stx
>    ;#:literals (...) ; Doesn't help :(
>    [(_ var:id)
>     #'(declare-with-set-transformer var (gensym 'unintialized))]
>    [(_ var:id init-val:expr)
>     (let ([store-name (gensym (syntax->datum #'var))])
>       #`(begin
>           (define #,store-name init-val)
>           (splicing-let ([set (lambda (val)
>                                 (set! #,store-name val))])
>             (define-syntax var
>               (make-set!-transformer
>                (lambda (stx)
>                  (syntax-case stx (set!)
>                    [(set! id val) #'(set val)]
>                    ; Uses Racket's #%app, which doesn't work for arc
>                    [(id . args) #'(#,store-name . args)] ; function application
>                    ; Obviously invalid syntax
>                    ;[(id . args) #'(arc-#%app #,store-name . args)]
>                    ; Errors because ... isn't recognized as a literal
>                    ;[(id args ...) #'(arc-#%app #,store-name args ...)]
>                    [id (identifier? #'id) #'#,store-name])))))))]))
>
> ; Demo of what I'm looking for
> (define test (make-hash))
> (hash-set! test 'key 'value)
> (displayln (arc-#%app test 'key))
>
> ; Example of what doesn't work right now
> (declare-with-set-transformer test2 (make-hash))
> (hash-set! test2 'key 'value)
> (displayln (test2 'key))
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users


Posted on the users mailing list.