[plt-scheme] namespace-attach-module

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sun Feb 4 18:22:48 EST 2007

At Sun, 04 Feb 2007 23:52:06 +0100, Jakub Piotr Cłapa wrote:
> I'm trying to load an external file and execute it in the namespace of a 
> required module as a means of UI for my simple commandline app.
> I'm doing something like this:
> (module avrp mzscheme
>    (require "avr-isp.scm")
>    (open-isp-device)
>    (with-handlers ([exn:fail:user? (lambda (exn)
>                               (send-request 'disconnect)
>                               (printf "~A~n" (exn-message exn)))])
>      (let ([new-ns (make-namespace)])
>        (define (module-path->symbol module-path)
>          ((current-module-name-resolver) module-path 'avr-isp #f #f))
>        (namespace-attach-module (current-namespace) (module-path->symbol 
> "avr-isp.scm") new-ns)
>        (parameterize ([current-namespace new-ns])
>          (namespace-require '(file "avr-isp.scm"))
>          (load "script.avrp")))
>    )
> )
> And it works (also with different combinations of parameters to the 
> resolver or even without the resolver) in
> mzscheme -tvm- avrp.scm

But it only works when you're in the same directory as "avrp.scm", right?
If you run

 % mkdir tmp
 % cd tmp
 % mzscheme -tvm- ../arvp.scm

you'll get an error.

The `mzc --exe' result is essentially the same problem. Even when you
run the generated executable in the same directory as the source, the
modules are embedded by `mzc --exe' into a kind of parallel filesystem.
When you call the module name resolver, "avr-isp.scm" doesn't refer to
that parallel filesystem.

The second argument to the module name resolver lets you specify
"avr-isp.scm" relative to some other module. For that argument, you
want a reference to the enclosing module's (run-time) name. One way to
get that name is to use `syntax-source-module' on a quoted syntax
constant within the module; then you have to recur on the result, in
case the result is relative to some other path... see below. Yes, there
should be a nicer way to do this.



(module avrp mzscheme
  (require "avr-isp.scm")

   (with-handlers ([exn:fail:user? (lambda (exn)
                                     (printf "~A~n" (exn-message exn)))])

     (let ([new-ns (make-namespace)])
       (define (module-path->symbol module-path)
          (let loop ([m (syntax-source-module #'here)])
            (if (symbol? m)
                (let-values ([(name base) (module-path-index-split m)])
                   (if base (loop base) #f)
          #f #f))
       (let ([name (module-path->symbol "avr-isp.scm")])
         (namespace-attach-module (current-namespace) 
         (parameterize ([current-namespace new-ns])
           (namespace-require name)
           (load "script.avrp"))))

Posted on the users mailing list.