[racket] Problem with Unhygienic Provide-Syntax

From: Gustavo Massaccesi (gustavo at oma.org.ar)
Date: Thu Feb 2 14:30:48 EST 2012

I tried to define some "marked" identifiers, and provide them using
"(all-defined-out)" with the same mark. The marks are introduced
unhygienicaly.

The problem is that some in additional marks are introduced during the
expansion, so in the example
"(provide (all-defined-marked-out))"
provides only the identifier "one", but does not provide the identifier "two".

(See the "Short Example" code below.)

I couldn't find a short and elegant solution. I want to know if there
is a better way to do this.



In my solution, the big changes were:

(See the "Long Example" code in the attached files.)

* In provide-trampoline: Add a few syntax-local-introduce to cancel
the syntax-marks before the expansion and mark them again after the
expansion.

* In make-provide-macro: Save the temporal syntax-introducer in a
parameter to be able to call it with "my-syntax-local-introduce" to
break hygiene. I think that it is not possible to modify the marker in
"syntax-local-introduce", so I created my own version.

And some small changes:

* In provide: It calls my versions of provide-trampoline.

* In define-provide-syntax: It calls my versions of make-provide-macro.


;=== begin provide-short-example.rkt
#lang racket/base
(require "provide-short.rkt")


(provide (all-defined-marked-out))    ;Provides: one       :(
(provide-all-defined-marked-out)      ;Provides: one, two  :)

(define one 1)

(define-marked two 2)
;=== end provide-short-example.rkt

; ------------------------------------

;=== begin provide-short.rkt
#lang racket/base
(require (for-syntax racket/base))
(require racket/provide-syntax)

(provide (all-defined-out))


; *** extra-marker ***

(define-for-syntax extra-marker (make-syntax-introducer))


; *** define ***

(define-syntax (define-marked stx)
  (syntax-case stx ()
    [(_ var val) (identifier? #'var)
     (with-syntax ([mk-var (syntax-local-introduce
                            (extra-marker
                             (syntax-local-introduce #'var)))])
       #'(define mk-var val))]))


; *** provide ***

(define-syntax (provide-all-defined-marked-out stx)
  (syntax-case stx ()
    [(_) (with-syntax ([\mk-all-defined-out/
                        (syntax-local-introduce
                         (extra-marker
                          (syntax-local-introduce
                           (datum->syntax stx (syntax-e
#'(all-defined-out))))))])
           #'(provide \mk-all-defined-out/))]))


(define-provide-syntax (all-defined-marked-out stx)
  (syntax-case stx ()
    [(_) (syntax-local-introduce
          (extra-marker
           (syntax-local-introduce
            (datum->syntax stx (syntax-e #'(all-defined-out))))))]))

;=== end provide-short.rkt
-------------- next part --------------
A non-text attachment was scrubbed...
Name: provide-example.rkt
Type: application/octet-stream
Size: 421 bytes
Desc: not available
URL: <http://lists.racket-lang.org/users/archive/attachments/20120202/f61eac18/attachment-0002.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: provide.rkt
Type: application/octet-stream
Size: 4806 bytes
Desc: not available
URL: <http://lists.racket-lang.org/users/archive/attachments/20120202/f61eac18/attachment-0003.obj>

Posted on the users mailing list.