[racket] define-provide-syntax + contract-out
I've learned about 'define-provide-syntax', and it works as expected in macro1 below with rename-out.
Macro2, which uses contract-out, doesn't work, reporting the error "contract-out: not a provide sub-form." I gather this is the result of the macro not seeing a binding for contract-out.
But where is it supposed to get the binding? I've moved (require racket/contract) around the macro to no avail.
PS. What is the point of this macro? To define a function with a contract in the usual way in the module source, but then move the contract inside a submodule, so it is only invoked on request.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#lang racket/base
(module macro1 racket
(require racket/provide-syntax)
(provide define-special)
(define-provide-syntax (r-out stx)
(syntax-case stx ()
[(_ name)
#'(rename-out [name foobar])]))
(define-syntax (define-special stx)
(syntax-case stx ()
[(_ (name arg) body ...)
#'(begin
(module+ inner
(define (name arg) body ...)
(provide (r-out name))))])))
(module macro2 racket
(require racket/provide-syntax)
(require racket/contract) ; nope
(require (for-syntax racket/contract)) ; nope
(provide define-special2)
(define-provide-syntax (c-out stx)
(syntax-case stx ()
[(_ name contract)
#'(contract-out [name contract])]))
(define-syntax (define-special2 stx)
(syntax-case stx ()
[(_ (name arg) contract body ...)
#'(begin
(define (name arg) body ...)
(module+ safe
(require racket/contract) ; nope
(provide (c-out name contract))))])))
(require 'macro1 'macro2)
(define-special (func x) x)
;> [works fine]
(define-special2 (func2 x) (string? . -> . string?) x)
;> contract-out: not a provide sub-form in: (contract-out (func2 (-> string? string?)))