[racket] ... in macro defining macros?

From: Nick Sivo (nick at kogir.com)
Date: Fri Aug 3 23:51:46 EDT 2012

Hi Jon,

Thanks, that works perfectly!

Did I miss that somewhere in the documentation?  I don't recall seeing
an example of it.

Best,
Nick

On Thu, Aug 2, 2012 at 11:55 PM, Jon Rafkind <rafkind at cs.utah.edu> wrote:
> 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
>
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users

Posted on the users mailing list.