[R6RS] modules?

Matthew Flatt mflatt
Tue Apr 20 11:01:43 EDT 2004

At Mon, 19 Apr 2004 21:26:48 -0500 (EST), "R. Kent Dybvig" wrote:
> In response to an earlier question, here are some common uses of internal
> modules:

I understand the theory, but I'm interested in seeing actual code that
uses SC. (I think I learn a lot by seeing realistic examples in
addition to abstract/contrived examples.) Any pointers to realistic

> Local imports are even more useful.

I definitely see this point --- they would solve certain implementation
problems in DrScheme. (I can elaborate if others are interested.)

> While it's true that internal modules don't work quite the same as
> top-level modules, this is really just a reflection of the top level and
> the concessions we make with it for interactive programming. 

Suppose that I'm willing to concede interactive programming, instead,
and the program I want to write is

 ; In MzScheme notation
 (module m mzscheme
   (define table ... #| big computation |# )
   (define (helper args) ...)
   (provide helper))
 (module n mzscheme
   (require m)
   (require-for-syntax m)
   (define-syntax (macro stx) ... (helper arg) #| not in template |# ...)
   (define x ... (marco stx) ... (helper arg) ...))

 ; In Chez notation
 (module m (helper)
   (define table ... #| big computation |# )
   (define (helper args) ...))
 (module n ()
   (require m)
   (define-syntax (macro stx) ... (helper arg) #| not in template |# ...)
   (define x ... (marco stx) ... (helper arg) ...))

To make sure my modules behave like internal modules, I'll wrap my
program in `let'. But the following doesn't work:

 (let ()
   (module m (helper)
     (define table ... #| big computation |# )
     (define (helper args) ...))
   (module n ()
     (require m)
     (define-syntax (macro stx) ... (helper arg) #| not in template |# ...)
     (define x ... (marco stx) ... (helper arg) ...))

How should I write the `m' module so that I can use it in both macro
implementations and run-time expressions?

> First, Chez Scheme allows imported variables to be assigned.  From brief
> experimentation, it appears that MzScheme does not. 

That's correct (and it's a big gap in the docs, I see). As you must
suspect, it's related to the next point.

> Second, Chez Scheme requires that hidden exports be explicitly associated
> with the corresponding export

How do you deal with macro-generating macros that also introduce
regular definitions that are private to generated macro?

For example, the code at the bottom of this message implements
`define-cbr' for first-order, call-by-reference functions.

 (define-cbr (f a b)
   (set! a b))

 (let ([x 1] [y 2])
   (f x y)
   x) ; result is 2

The implementation strategy is that `define-cbr' expands to a
`define-syntax' for the name `f', plus a `define' of the private
function `do-f' that is references by the expansion of an `f' use.

A programmer can't access the name `do-f', so it wouldn't make sense to

 (module m ((f do-f))
   (define-cbr (f a b) (set! a b)))

[This particular example is taken from a recent Dr. Dobb's Journal
 article, so it's contrived in that sense. But some macros in
 DrScheme's implementation do the same thing, including
 `define/contract' and `package'.]

> If all identifiers are made available, there's not
> much security, since a macro writer can unintentionally allow fishing
> for hidden exports:

I agree that this is a problem, and it's not one that we've solved in

The bigger problem, for us, is that we'd like to restrict access to
identifiers that do show up in macro expansions, too. In other words,
we want the identifier used only in the context that the macro gives
it. So there's a more general problem that I think must have a more
general solution.



(define-syntax define-get/set-var
  (syntax-rules ()
    [(define-get/set-var id get set)
     (define-syntax id
       ;; syntax-id-rules is like syntax-rules, but supports id macros
       (syntax-id-rules (set!)
	 [(set! id e) (set e)]
	 [(id a (... ...)) ((get) a (... ...))]
	 [id (get)]))]))

(define-syntax define-cbr
  (syntax-rules ()
    [(_ (id arg ...) body)
       (define-cbr-as-cbv do-f (arg ...)
	 () body)
       (define-syntax id
	 (syntax-rules ()
	   [(id actual (... ...))
	    (do-f (lambda () actual) 
		  (... ...)
		  (lambda (v) 
		    (set! actual v))
		  (... ...))])))]))

(define-syntax define-cbr-as-cbv
  (syntax-rules ()
    [(define-cbr-as-cbv do-f (arg0 arg ...)
       (gens ...) body)
     (define-cbr-as-cbv do-f (arg ...) 
       (gens ... (arg0 get set)) body)]
    [(define-cbr-as-cbv do-f ()
       ((arg get set) ...) body)
     (define (do-f get ... set ...)
       (define-get/set-var arg get set) ...

More information about the R6RS mailing list