[racket] define-syntax-rule/id

From: Laurent (laurent.orseau at gmail.com)
Date: Mon Apr 18 12:21:38 EDT 2011

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/c31cb761/attachment.html>

Posted on the users mailing list.