<div dir="ltr">Yes, I like dynamic-rerequire. Because it already has the file-watching facility built in, I rely on it as a sort of sonar device to find out if a source file has changed, like so:<div><br></div><div>(define (source-changed? source-path)</div>
<div><br></div><div><div>  (define port-for-catching-file-info (open-output-string))</div><div> </div><div>  (parameterize ([current-directory source-dir]<br></div><div>                 [current-error-port port-for-catching-file-info])</div>
<div>    (dynamic-rerequire source-path))</div><div>  </div><div>  ((length (get-output-string port-for-catching-file-info)) . > . 0)))<br></div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Oct 14, 2013 at 12:31 PM, Matthew Flatt <span dir="ltr"><<a href="mailto:mflatt@cs.utah.edu" target="_blank">mflatt@cs.utah.edu</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I think the advice that Robby gives is probably better, but...<br>
<br>
If you only need to pick up changes to a module (as opposed to running<br>
a module afresh for its side effects), and if you're using 5.90.x, you<br>
could try using `dynamic-rerequire` in a single namespace to reload<br>
modules.<br>
<div class="HOEnZb"><div class="h5"><br>
At Mon, 14 Oct 2013 13:22:21 -0500, Robby Findler wrote:<br>
> Did you try using namespace-attach-module to attach 'racket and<br>
> 'web-server/templates? Something like:<br>
><br>
>   (define orig-ns (current-namespace))<br>
>   (parameterize ([current-namespace (make-base-empty-namespace)])<br>
>     (namespace-attach-module orig-ns 'racket)<br>
>     (namespace-attach-module orig-ns 'web-server/templates)<br>
>     (namespace-require 'racket)<br>
>     (eval `(begin<br>
>              (require web-server/templates)<br>
>              (require ,my-source-path-string)<br>
>              (include-template ,my-template-path-string))<br>
>           (current-namespace)))<br>
><br>
> But 7 seconds seems remarkably long (I see a speed up of about 50% for that<br>
> function (with the my-source-path-string and my-template-path-string lines<br>
> commented out): from 250 to 170 msec).<br>
><br>
> It may be that your .zo files or something are not up to date. So you may<br>
> want to stick a 'raco make' somewhere in there to avoid recompiling your<br>
> files every time and just recompile the ones that changed.<br>
><br>
> Robby<br>
><br>
><br>
><br>
><br>
> On Mon, Oct 14, 2013 at 1:14 PM, Matthew Butterick<br>
> <<a href="mailto:mb.list.acct@gmail.com">mb.list.acct@gmail.com</a>>wrote:<br>
><br>
> > At RacketCon I talked about my Pollen system for making web pages. Though<br>
> > I don't use the Racket webserver to provide live generation of web pages, I<br>
> > do use it to provide a kind of browser-assisted REPL for development. As I<br>
> > edit the project files, I want to reload the URL in the browser and see the<br>
> > changes (without restarting the webserver).<br>
> ><br>
> > Moreover, since it's a development tool, it wants to be maximally dynamic.<br>
> > For instance, I might be editing source files containing page content, or<br>
> > the design templates (which might also contain Racket code), or supporting<br>
> > Racket libraries (e.g., CSS generators).<br>
> ><br>
> > Jay has suggested that this can be done with eval. And indeed it can.<br>
> > Here's the quasicode I use:<br>
> ><br>
> >   (parameterize ([current-namespace (make-base-empty-namespace)])<br>
> >     (namespace-require 'racket)<br>
> >     (eval `(begin<br>
> >              (require web-server/templates)<br>
> >              (require ,my-source-path-string)<br>
> >              (include-template ,my-template-path-string))<br>
> >           (current-namespace))))<br>
> ><br>
> > This works great, with one wrinkle: it's the slowest operation in the<br>
> > whole system, taking about 7-8 secs to render each page. This is not a<br>
> > grave hardship, and certainly faster than restarting the web server. But<br>
> > I'd still be curious if I'm overlooking a better approach.<br>
> ><br>
> > In general, the render time is fairly consistent regardless of what's in<br>
> > the page, which suggests to me that most of the expense comes from setting<br>
> > up the fresh namespace. I did try making a namespace separately and reusing<br>
> > it, but that didn't work (code wouldn't get reloaded). Is there a way to<br>
> > "clean" a namespace that's cheaper than setting up a new one?<br>
> ><br>
> > Another option I considered is starting up another instance of Racket in a<br>
> > subprocess, but it would need to be made into a synchronous operation. Long<br>
> > drive for a short day at the beach, etc.<br>
> ><br>
> > It's also possible that I'm running up against the irreducible cost of<br>
> > high-quality eval, in which case, I will accept it and move on.<br>
> ><br>
> ><br>
> > Matthew Butterick<br>
> ><br>
> ><br>
> ><br>
> ><br>
> > On Thu, Jun 6, 2013 at 7:36 PM, Greg Hendershott <<br>
> > <a href="mailto:greghendershott@gmail.com">greghendershott@gmail.com</a>> wrote:<br>
> ><br>
> >> Great timing! It's been on my short list to make my static blog<br>
> >> generator more flexible. From<br>
> >> <a href="http://docs.racket-lang.org/web-server/templates.html" target="_blank">http://docs.racket-lang.org/web-server/templates.html</a> I got the idea<br>
> >> that it would be suitable only for static templates, but now I<br>
> >> understand that's not the case. Today I made a topic branch using this<br>
> >> approach that's working well, which I plan to merge after some testing<br>
> >> and polishing.<br>
> >><br>
> >> p.s. Maybe it's obvious, but because `include-template` uses<br>
> >> `include-at/relative-to/reader`, it won't include a template if you<br>
> >> give it a full path. Maybe there's a more-elegant way, but I found it<br>
> >> worked to parameterize `current-directory` around the call to `eval`.<br>
> >><br>
> >><br>
> >> On Wed, Jun 5, 2013 at 4:45 PM, Jay McCarthy <<a href="mailto:jay.mccarthy@gmail.com">jay.mccarthy@gmail.com</a>><br>
> >> wrote:<br>
> >> > While it is supposed to be pithy, it is also serious.<br>
> >> ><br>
> >> > When I wrote it, I imagine that people would do something like this:<br>
> >> ><br>
> >> > #lang racket/base<br>
> >> > (require web-server/templates)<br>
> >> ><br>
> >> > (define (template-content t x)<br>
> >> >   (eval #`(let ([x #,x]) (include-template #,t))))<br>
> >> ><br>
> >> > (template-content "t.txt" 5)<br>
> >> > (template-content "t.txt" 6)<br>
> >> ><br>
> >> > and trust that the template wouldn't include @(system "rm -fr /"). I<br>
> >> > think that a simple eval works just fine for when you, the programmer,<br>
> >> > want to change the content dynamic (although I'd say it is better to<br>
> >> > use the web-server language so you can restart with the same<br>
> >> > continuations, etc.)<br>
> >> ><br>
> >> > Your solution is great for a template that a user provides, although<br>
> >> > it has the hole that the template could call @include-template and<br>
> >> > maybe find itself and go into a infinite loop, so it's not totally<br>
> >> > "secure" unless you use a sandbox.<br>
> >> ><br>
> >> > Jay<br>
> >> ><br>
> >> > On Wed, Jun 5, 2013 at 1:53 PM, Joe Gibbs Politz <<a href="mailto:joe@cs.brown.edu">joe@cs.brown.edu</a>><br>
> >> wrote:<br>
> >> >> I'm writing a web server in a #lang that doesn't support macros or<br>
> >> >> syntactic abstraction.  I would like to be able to use some sort of<br>
> >> >> templating dynamically with bindings given by values, e.g.<br>
> >> >><br>
> >> >> template.render("page-with-hole-for-username.html", { username: "Joe"<br>
> >> })<br>
> >> >><br>
> >> >> The FAQ (<br>
> >><br>
> <a href="http://docs.racket-lang.org/web-server/faq.html#(part._.How_do_.I_use_templates" target="_blank">http://docs.racket-lang.org/web-server/faq.html#(part._.How_do_.I_use_templates</a><br>
> __dynamically__)<br>
> >> )<br>
> >> >> in the documentation for templates ends with this pithy<br>
> >> >> recommendation:<br>
> >> >><br>
> >> >> "If you insist on dynamicism, there is always eval."<br>
> >> >><br>
> >> >> I assume this isn't intended seriously, and instead to discourage what<br>
> >> >> I'm asking about, but I'm unfortunately not seeing another way to<br>
> >> >> write my program.  The code at the end of this message seems like the<br>
> >> >> best I can do while being relatively safe, but also like a dubious<br>
> >> >> inclusion on a web server given the eval.<br>
> >> >><br>
> >> >> Is this the best I can hope for?  Is there another collection I should<br>
> >> >> be looking into?  Any other recommendations?<br>
> >> >><br>
> >> >> Thanks!<br>
> >> >> Joe P.<br>
> >> >><br>
> >> >><br>
> >> >> #lang racket/base<br>
> >> >><br>
> >> >> (require<br>
> >> >>   web-server/templates)<br>
> >> >><br>
> >> >> (define (render-template filename dict)<br>
> >> >>   (define namespace-for-template (make-empty-namespace))<br>
> >> >>   (namespace-attach-module (current-namespace) 'web-server/templates<br>
> >> >> namespace-for-template)<br>
> >> >>   (hash-map dict<br>
> >> >>     (lambda (key value)<br>
> >> >>       (define name-of-identifier (string->symbol key))<br>
> >> >>       (namespace-set-variable-value!<br>
> >> >>         name-of-identifier<br>
> >> >>         value<br>
> >> >>         #f<br>
> >> >>         namespace-for-template)))<br>
> >> >>   (parameterize [(current-namespace namespace-for-template)]<br>
> >> >>     (namespace-require 'web-server/templates))<br>
> >> >>   (define to-eval #`(include-template #,(datum->syntax<br>
> >> >> #'render-template filename)))<br>
> >> >>   (eval to-eval namespace-for-template))<br>
> >> >> ____________________<br>
> >> >>   Racket Users list:<br>
> >> >>   <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
> >> ><br>
> >> ><br>
> >> ><br>
> >> > --<br>
> >> > Jay McCarthy <<a href="mailto:jay@cs.byu.edu">jay@cs.byu.edu</a>><br>
> >> > Assistant Professor / Brigham Young University<br>
> >> > <a href="http://faculty.cs.byu.edu/~jay" target="_blank">http://faculty.cs.byu.edu/~jay</a><br>
> >> ><br>
> >> > "The glory of God is Intelligence" - D&C 93<br>
> >> > ____________________<br>
> >> >   Racket Users list:<br>
> >> >   <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
> >> ____________________<br>
> >>   Racket Users list:<br>
> >>   <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
> >><br>
> ><br>
> ><br>
> > ____________________<br>
> >   Racket Users list:<br>
> >   <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
> ><br>
> ><br>
> ____________________<br>
>   Racket Users list:<br>
>   <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
</div></div></blockquote></div><br></div>