[plt-scheme] Problem with macro generated provide/contract

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Sun Nov 6 07:04:14 EST 2005

Matthew Flatt wrote:
> At Sat, 05 Nov 2005 22:14:43 +0100, Jens Axel Søgaard wrote:
>>(module list-signature mzscheme
>>   (provide provide-list-operations)
>>   (define-syntax provide-list-operations
>>     (syntax-rules ()
>>       [(provide-list-operations)
>>        (provide mycons mycar myempty)])))
>>Our original mylist1 without signatures now become:
>>(module mylist2 mzscheme
>>   (define mycons cons)
>>   (define myempty '())
>>   (define mycar car)
>>   (require list-signature)
>>   (provide-list-operations))
> I think this shouldn't have worked. (I know why it works in the current
> implementation.)
> `require' and `provide' are supposed to be sensitive to the lexical
> context of specific imports/exports. In particular, a macro-introduced
> `require' is supposed to bind in the same way as a macro-introduced
> `define', and a macro-introduced `provide' is supposed to behave like a
> macro-introduced reference.


> Since `(provide mycons ...)' is introduced in the above example from a
> context with no `mycons', then it shouldn't have worked.
> I'll look into fixing this bug. Then, you'd have to make
> `provide-list-operations' non-hygienic:

That makes sense.

>     (define-syntax (provide-list-operations stx)
>       (syntax-case stx ()
>         [(_)
>          (with-syntax ([mycons (datum->syntax-object stx 'mycons)]
>                        [mycar (datum->syntax-object stx 'mycar)]
>                        [myempty (datum->syntax-object stx 'myempty)])
>            #'(provide mycons mycar myempty))]))
> This same strategy should work for `provide/contract'.

I tried this (and variations thereof):

(module list-signature-with-contracts mzscheme
   (provide provide-list-operations-with-contracts)
   (define-syntax provide-list-operations-with-contracts
     (syntax-rules ()
          (require (lib "contract.ss"))
          (define pair/c (flat-named-contract 'pair pair?))
          (define-syntax (provide-list-operations stx)
            (syntax-case stx ()
                  ([mycons  (datum->syntax-object stx 'mycons)]
                   [mycar   (datum->syntax-object stx 'mycar)]
                   [myempty (datum->syntax-object stx 'myempty)])
                     (mycons (-> any/c any/c  pair/c))
                     (mycar  (-> pair/c  any/c))))])))])))

(module mylist2-with-contracts mzscheme
   (define mycons cons)
   (define myempty '())
   (define mycar car)

   (require list-signature-with-contracts)

(require mylist2-with-contracts)
(mycons 1 2)

But I keep getting the error:

     reference to undefined identifier: mycons

Jens Axel Søgaard

Posted on the users mailing list.