[racket] Evaluating Racket source files from within another Racket source file

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sat Apr 27 22:17:22 EDT 2013

I think you probably want to create a new namespace for each
instantiation of the Scribble module, and attach Scribble (or whatever
modules you want to stay the same across runs) to the namespace before
`dynamic-require'ing the module in the new namespace:

 #lang racket/base
 (require scribble/base)

 (define (re-run module-path)
   (define ns (make-base-namespace))
   (namespace-attach-module (current-namespace) 'scribble/base)
   (parameterize ([current-namespace ns])
     (dynamic-require module-path #f)))


At Sat, 27 Apr 2013 19:08:53 -0700, Matthew Butterick wrote:
> OK, so the proposed solution failed once I tried to pass in the module name
> as a variable. Even though enter! claims to take a module-path as an
> argument, this will not work:
> 
> (define name "module.rkt")
> (module-path? name) ; reports #t
> (enter! name) ;  error: collection "name" not found
> 
> enter! is treating "name" as a module path instead of resolving it as a
> defined term. What I can't tell is whether this is mandatory behavior for
> enter!, or if it's a bug in the enter! macro. (I did look at enter.rkt, but
> this week, it's over my head.)
> 
> Matthew Butterick
> 
> 
> On Sat, Apr 27, 2013 at 6:16 PM, Matthew Butterick
> <mb.list.acct at gmail.com>wrote:
> 
> > Aha, combining enter! with dynamic-require seems to do the trick:
> >
> > (define (route req)
> >     (enter! "module.rkt")
> >     (define foo (dynamic-require "module.rkt" 'foo))
> >     (response/xexpr `(p ,(format "~a" foo))))
> >
> > Once this route is running in the web server, I can make changes to
> > module.rkt, then click reload in the browser, and the changes will appear
> > in the browser.
> >
> > If this is a terrible idea let me know, otherwise I'll consider this
> > solved.
> >
> >
> > On Sat, Apr 27, 2013 at 9:56 AM, Matthew Butterick <mb.list.acct at gmail.com
> > > wrote:
> >
> >> I'm building a website using Scribble as the source format. As a
> >> development tool, I've built a web server in Python that lets me view all
> >> my Scribble source files and look at them in different states of
> >> processing. To view the results of the Scribble files, the Python server
> >> just sends the files to Racket via a system command (os.Popen) and reads
> >> the result. This works but it's slow, because it  has to launch a new
> >> Racket thread for every request.
> >>
> >> I thought I could speed things up by rewriting the development web server
> >> in Racket. But having tried a few approaches, I'm not sure how to duplicate
> >> this functionality within a Racket web servlet:
> >>
> >> *(require <modulename>) *
> >> This only gets evaluated once, when the server is started. That doesn't
> >> help, since the <filename> is going to be passed in as a parameter while
> >> the server is running.
> >>
> >> *(dynamic-require <** modulename **>) *
> >> This gets evaluated only when invoked, and thus can take <modulename> as
> >> a parameter, but then <filename> can't be reloaded (this is essential, as
> >> the point of the system is to be able to edit the files and see the changes
> >> in the web browser immediately)
> >>
> >> *(enter! <modulename>)*
> >> This reloads the file, but it's not clear how to get access to names
> >> provided by <modulename>. (The documentation for enter! suggests that this
> >> is not how it's meant to be used anyhow.)
> >>
> >> Obviously, I could call a new instance of Racket as a system command, but
> >> that wouldn't offer any advantage over the current approach.
> >>
> >>
> >> I suppose what I'm looking for is an equivalent of the Python
> >> reload(<modulename>) command.
> >>
> >>
> >> Matthew Butterick
> >>
> >
> >
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users

Posted on the users mailing list.