[plt-scheme] Wrapping non-PLT code in modules

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Tue Oct 29 15:41:00 EST 2002

At Tue, 29 Oct 2002 12:21:30 -0500, "Anton van Straaten" wrote:
> So, I tried providing a relative path to collects/lang/r5rs.ss.  This failed
> because of not having "provide" and "require" defined in that "language".
> So I copied r5rs.ss and added "provide" and "require" to its provide
> statement.  That worked!  Cool.  (I think.  I haven't run into any
> show-stopping problems with it yet...)
> 
> My question is, is there a simple|recommended|obvious way to do this that
> I've missed?

I expected the recommended way to be simple and obvious, but it isn't.
Requiring and re-exporting `(lib "r5rs.ss" "lang")' is tricky --- too
much overlap with `mzscheme', and not enough renaming operators within
`provide'.

The simplest way I can recommend replies on one helper module:

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

(module almost-nothing mzscheme
  (provide #%module-begin
	   provide
	   require))

(module r5rs-rpi "almost-nothing.ss"
  (require (all-except (lib "r5rs.ss" "lang") #%module-begin)
	   (rename (lib "r5rs.ss" "lang") r5rs-module-begin #%module-begin)
	   (lib "include.ss"))

  (provide (all-from (lib "r5rs.ss" "lang"))
	   (rename r5rs-module-begin #%module-begin)
	   require
	   provide
	   include))

(module wrapped-demo "r5rs-rpi.ss"   
  (include "demo.scm")
  (provide foo goo)) ; if foo & goo are defined in demo.scm

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

Then I decided to go for something a little fancier. Suppose I don't
want `require', `provide', and `include' bound in my R5RS code. Here's
one way.

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

(module r5rs-wp "almost-nothing.ss"
  (require (all-except (lib "r5rs.ss" "lang") #%module-begin)
	   (rename (lib "r5rs.ss" "lang") r5rs-module-begin #%module-begin)
	   (lib "include.ss"))

  ;; defines a module top-level that contains just a file
  ;;  name and a parenthesized sequence of exports
  (define-syntax (wrap-module-begin stx)
    (syntax-case stx ()
      [(_ file-name (export ...))
       (string? (syntax-e #'file-name))
       #'(r5rs-module-begin
	  (include-at/relative-to file-name file-name file-name)
	  (provide export ...))]))

  (provide (all-from (lib "r5rs.ss" "lang"))
	   #%module-begin
           provide
	   wrap-module-begin))

(module r5rs-wrap "r5rs-wp.ss"
  (provide (all-from-except "r5rs-wp.ss" provide #%module-begin)
	   (rename wrap-module-begin #%module-begin)))

(module wrapped-demo "r5rs-wrap.ss"
  "demo.scm"
  (foo goo))

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

Amusing, but even in this case, `#%module-begin' is still bound in the
R5RS code. For that matter, so is `#%app', etc. But those are not legal
R5RS identifiers.

Ok, so why not just add `#%require' and `#%provide' to the exports of
`(lib "r5rs.ss" "lang")'? Done.

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

(module wrapped-demo (lib "r5rs.ss" "lang") ; <- the new r5rs.ss
  (#%require (rename (lib "include.ss") #%include include))
  (#%include "demo.scm")
  (#%provide foo goo))

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

Matthew



Posted on the users mailing list.