[racket-dev] A strange problem with namespaces

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Wed May 7 11:57:02 EDT 2014

I see. The errors are about the modules that require "evaluator.rkt".
That is, the modules that use `phase1-phase0-eval` need to be
available, not just "evaluator.rkt", so that transformer bindings in
those modules can be used.

So,

 (define (prep! varref)
   (define p (variable-reference->resolved-module-path varref))
   (when p
     (parameterize ([current-namespace namespace])
       (dynamic-require p 0))))

 ...

 (define-syntax phase1-phase0-eval
   (syntax-parser
     [(_ form:expr ...)
      #'(begin 
          (prep! (#%variable-reference))
          (eval-syntax ....))]))

  (define-syntax phase1-eval
    (syntax-parser
      [(_ form:expr ...)
       #'(begin
           (prep! (#%variable-reference))
           (phase1-phase0-eval ....))]))

A way to look at it is that you want an anchor in each module that uses
`phase1-phase0-eval`, and `(#%variable-reference)` is the primitive
form of an anchor.

At Wed, 7 May 2014 11:43:39 -0400, Sam Tobin-Hochstadt wrote:
> On Wed, May 7, 2014 at 11:07 AM, Sam Tobin-Hochstadt
> <samth at cs.indiana.edu> wrote:
> > Great, thanks!
> 
> Also, can you say more about when this trick is needed? When I try to
> use it in the actual code that I want to run, I end up with the same
> error, or about other submodules that are missing.
> 
> More specifically, I added `prep!` to
> `tests/typed-racket/unit-tests/evaluator.rkt` and then ran this
> program:
> 
>     #lang racket
>     (define ns (make-base-namespace))
>     (current-namespace ns)
>     ((dynamic-require 'tests/typed-racket/main 'go/text)
>      (dynamic-require 'tests/typed-racket/main 'unit-tests))
> 
> It produces lots of errors, of the same form that `weird.rkt` had
> before the `prep!` fix.  You get the same errors if you take out the
> namespace.
> 
> However, there aren't any other uses of namespace anchors in that
> code, so I'm not sure what to try to fix.
> 
> Sam
> 
> 
> >
> > On Wed, May 7, 2014 at 10:58 AM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> >> I think the right change might be
> >>
> >>  (module evaluator racket
> >>    ....
> >>    (define (prep!)
> >>      (parameterize ([current-namespace namespace])
> >>        (dynamic-require (variable-reference->module-path-index
> >>                          (#%variable-reference))
> >>                         0)))
> >>    ....
> >>    (define-syntax phase1-phase0-eval
> >>      (syntax-parser
> >>       [(_ form:expr ...)
> >>        #'(begin
> >>            (prep!)
> >>            (eval-syntax .....))])))
> >>
> >> The `prep!` function ensures that the enclosing module is available.
> >>
> >> At Wed, 7 May 2014 10:11:49 -0400, Sam Tobin-Hochstadt wrote:
> >>> This program: https://gist.github.com/samth/e7b55fcef66da9b8416a works
> >>> when line 33 is uncommented, otherwise it gives the error:
> >>>
> >>> ?: module mismatch;
> >>>  attempted to use a module that is not available
> >>>   possible cause:
> >>>    using (dynamic-require .... #f)
> >>>    but need (dynamic-require .... 0)
> >>>   module: (submod "weird.rkt" evaluator)
> >>>   phase: 0
> >>>   in: phase1-phase0-run
> >>>   context...:
> >>>    weird.rkt: [running body]
> >>>
> >>> From reading the docs on `dynamic-require`, I can see that
> >>> `(dynamic-require m 'f)` doesn't make anything available for higher
> >>> phases.  However, the actual `dynamic-require` in the program is just
> >>> for a function -- the need for higher phases is an implementation
> >>> detail that's leaking in because it doesn't behave like a regular
> >>> value wrt `dynamic-require`.
> >>>
> >>> Is there something I can change in the implementation of the internals
> >>> of `f` so that clients of `f` don't need to do the extra
> >>> `(dynamic-require m 0)` in order for `f` to work?
> >>>
> >>> Sam
> >>> _________________________
> >>>   Racket Developers list:
> >>>   http://lists.racket-lang.org/dev

Posted on the dev mailing list.