<div dir="ltr"><div><div>At RacketCon I talked about my Pollen system for making web pages. Though I don't use the Racket webserver to provide live generation of web pages, I do use it to provide a kind of browser-assisted REPL for development. As I edit the project files, I want to reload the URL in the browser and see the changes (without restarting the webserver). </div>
<div><br></div><div>Moreover, since it's a development tool, it wants to be maximally dynamic. For instance, I might be editing source files containing page content, or the design templates (which might also contain Racket code), or supporting Racket libraries (e.g., CSS generators).</div>
<div><br></div><div>Jay has suggested that this can be done with eval. And indeed it can. Here's the quasicode I use:</div><div><br></div><div>  (parameterize ([current-namespace (make-base-empty-namespace)]) </div><div>
    (namespace-require 'racket)</div><div>    (eval `(begin </div><div>             (require web-server/templates)</div><div>             (require ,my-source-path-string)</div><div>             (include-template ,my-template-path-string)) </div>
<div>          (current-namespace))))</div></div><div><br></div><div>This works great, with one wrinkle: it's the slowest operation in the whole system, taking about 7-8 secs to render each page. This is not a grave hardship, and certainly faster than restarting the web server. But I'd still be curious if I'm overlooking a better approach.</div>
<div><br></div><div>In general, the render time is fairly consistent regardless of what's in the page, which suggests to me that most of the expense comes from setting up the fresh namespace. I did try making a namespace separately and reusing it, but that didn't work (code wouldn't get reloaded). Is there a way to "clean" a namespace that's cheaper than setting up a new one?</div>
<div><br></div><div>Another option I considered is starting up another instance of Racket in a subprocess, but it would need to be made into a synchronous operation. Long drive for a short day at the beach, etc.</div><div>
<br></div><div>It's also possible that I'm running up against the irreducible cost of high-quality eval, in which case, I will accept it and move on.</div><div><br></div><div><br></div><div>Matthew Butterick<br></div>
<div><br></div><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Jun 6, 2013 at 7:36 PM, Greg Hendershott <span dir="ltr"><<a href="mailto:greghendershott@gmail.com" target="_blank">greghendershott@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">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>
<div class=""><div class="h5"><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>> 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>> 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>
>> The FAQ (<a href="http://docs.racket-lang.org/web-server/faq.html#(part._.How_do_.I_use_templates__dynamically__)" target="_blank">http://docs.racket-lang.org/web-server/faq.html#(part._.How_do_.I_use_templates__dynamically__)</a>)<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>
</div></div></blockquote></div><br></div></div>