[racket] define-syntax-rule/id

From: Laurent (laurent.orseau at gmail.com)
Date: Mon Apr 18 14:03:25 EDT 2011

Found!

After having read more carefully Eli's very good post (
http://blog.racket-lang.org/2011/04/writing-syntax-case-macros.html), it
became clearer that the problem was that the context of the created
identifier was wrong.
Deconstructing and reconstructing the id syntax object did the trick:

(define-syntax (define-syntax-rule/id stx)
  (syntax-case stx ()
    [(_ [id id-gen] body)
     (with-syntax ([id-def (to-syntax
                            (syntax-e (syntax-local-eval #'id-gen))
                            #:stx stx)])
       #'(splicing-let-syntax ([tmp-form (syntax-rules ()
                                  [(_ id) (begin (displayln 'body)
                                                 body)])])
            (tmp-form id-def))
       )]
    ))


Now if anyone knows a better way to implement this or can point out problems
with this implementation, I'd be glad to know about it.

Thanks for listening :)
Laurent


On Mon, Apr 18, 2011 at 18:21, Laurent <laurent.orseau at gmail.com> wrote:

> Dear Racket list,
>
> Once again, I need a little help on a macro definition.
>
> I want to define the following (simplified[1]) macro:
> (define-syntax-rule/id [*id id-gen*] *body*)
>
> where id is replaced with the result of id-gen inside body.
> For example:
> (define-syntax-rule/id
>   [x #'foo]
>   (begin (define x 5)
>          (displayln x)))
>
> is supposed to bind foo to 5 in the top-level at run-time.
> (You can replace #'foo by some complex identifier-making expression using
> format-id.)
> Here is what I have right now, after much trial&error:
>
> #lang racket
>
> (require (for-syntax unstable/syntax)
>          (for-syntax errortrace/errortrace-key)
>          racket/splicing
>          )
>
> (provide (all-defined-out))
>
> ;; Like define-syntax-rule,
> ;; but id is replaced with the result of id-gen in body.
> ;; id-gen is eval'ed at macro-time.
> (define-syntax (define-syntax-rule/id stx)
>   (syntax-case stx ()
>     [(_ [id id-gen] body)
>      (with-syntax ([id-def (syntax-local-eval #'id-gen)])
>        #'(splicing-let-syntax ([tmp-form (syntax-rules ()
>                                   [(_ id) (begin (displayln 'body)
>                                                  body)])])
>             (tmp-form id-def))
>        )]
>     ))
>
> ;;; TESTS
>
> (define-syntax-rule/id
>   [x #'foo]
>   (begin (define x 5)
>          (displayln x)
>          (displayln 'x)
>          ))
>
>
> It works (foo is bound to 5), except that foo is unknown (undefined
> identifier) after the (begin ...).
> I suspect this is because of syntax-local-eval, but I don't know what to
> use instead.
>
> There is another intriguing thing:
> if just after (define x 5) we add (provide x), and in another file we
> require the first file, then foo is actually defined and can be used
> normally!
> Why is that and why does this not work when there is no (provide x) ? [note
> that there is a (provide (all-defined out)).]
>
> Can someone give me a hint as to what is going on?
>
> I also suspect that using splicing-let-syntax is not the way to go, but
> again I don't know what to use otherwise, that would let me replace id with
> id-def.
>
> Thank you very much,
> Laurent
>
>
> [1] To explain the name: once finished, this macro will be supposed to
> behave like an augmented version of define-syntax-rule but with explicit
> hygiene breaking:
>
> (define-syntax-rule/id (make-getter id)
>   [id2 (format-id #'here "get-~a" id)]
>   (define (id2) id))
>
> which, when called on (make-getter foo) would create the get-foo function.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20110418/aada576e/attachment.html>

Posted on the users mailing list.