[racket-dev] Caching rendered icons

From: Eli Barzilay (eli at barzilay.org)
Date: Fri Jan 13 22:01:35 EST 2012

40 minutes ago, Neil Toronto wrote:
> 
> I have two problems with this. One of them I also have with Eli's
> suggestion: we'd end up with Racket distributions that have
> different performance characteristics depending on where they were
> compiled.

Our distributions would not.  For compilation, you can spit out a
warning that says that it didn't find cairo so images were not
precompiled and blah blah blah.  Better than an error, and clearer
that if you're not using images, then the warning is one you can live
with.


> My other problem with falling back to runtime rendering is that
> either 1) user code would have to compute every value they use to
> make icons both normally and for-syntax; or 2) I would have to break
> the nice abstraction I have now (wherein `compiled-bitmap' needs to
> know nothing about its inner expression) and serialize the arguments
> to the icon-constructing functions at compile-time and deserialize
> them at runtime. Option #1 sounds bad for the user - it would be
> easy to have icons that render differently depending on whether they
> were done at compile time or run time. Option #2 bothers me for a
> reason I can't quite explain.

This goes back to the point I made about confusing things.  Having a
kind of a macro that really puts parts of its body in the syntax level
is asking for problems.  IIUC, you have me start with something like

  (define x (foo a b c))

then, when I realize that I can optimize it and pre-compile the value,
not only do I need to change that to

  (define x (compiled-foo a b c))

I also need to arrange for the arguments to be available at the syntax
level.  So something that initially looks like a cute and quick way to
get a speed boost can turn into a long journy of factoring out parts
of your whole code into separate for-syntax modules.  I'm thinking
about these things as potential sprites for games etc, which means
that they should be accessible for most people -- and that kind of
switch immediately makes the whole thing unavailable for most.

BTW, the only example I have for such a thing is the `filtered-in'
and `filtered-out' that I added a while ago -- the intention was to
make it possible to write *simple* filter functions usually in plain
`racket/base'.  In addition, there is no refactoring there since it's
not like there's a runtime equivalent of require specs.  Still, it's
not used too often -- and what you're talking about is *much* more
involved than that.


> Eli's suggestion has me writing macros that act like functions,
> except that they parse the syntax of arguments and sometimes can run
> at compile time. A lot of currently runtime values would have to
> turn into macros, such as `run-icon-color'.

You can probably do that by having a binding that has a runtime and a
compile time information on it.  But...


> And I'd be writing an interpreter using syntax classes, a pale
> shadow of Racket.

...I think that you're misunderstanding me.  If you think about doing
something like

  (define foo (make-logo (combine (circle 30) (triangle 20))))

as something that you need to completely parse at runtime, then
obviously this is insane (and the "proper" thing would be to somehow
compile two copies of the code, one for syntax and one for runtime,
but that's a mess too).  Instead, have the code that makes the icon
contents in a module, then

  (define foo (render-icon-from "my-icon.rkt"))

can require and run that code at the syntax level, and produce the
prerendered bytestring, or it can expand to a plain require, as in

  (require "my-icon.rkt")
  (define foo (the-renderer))

Roughly.

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!


Posted on the dev mailing list.