Open jimbaker opened 1 year ago
Another way to see the outside-in evaluation approach is the usual pattern of code of
def mytag(*args: Chunk | Thunk):
for arg in args:
match arg:
# process arg by its type
This explicit evaluation enables a lot of the power of this approach, while being hidden in, it's just working with strings and interpolations.
Unlike the usual ordering in functions, evaluation is outside-in, vs inside-out. That is:
f(g(h(...)))
,h(...)
evaluates, theng
with its result, and thenf
, implicitly.html"<div>{html'<ul>{f()}</ul>'}</div>"
, we effectively have (Note that this is similar to a lot of code - it might explicitly iterate over an outer loop, then an inner loop, etc.
Because of this explicit, outside-in evaluation, it's possible to have the DSL template to control this scheduling as it "peels the onion" of thunks. For example, if rendering HTML, it could just evaluate what is visible up to that point in the scrolling (at least in principle). This also allows for an incremental output of results in general, similar to what is done in WSGI.
Next, for each interpolation, we only see
lambda: expr
(unless we try to do a rewrite trick to use the expr text and any lexically scoped names attached, but that's nontrivialin general). So we don't know necessary what the value ofexpr
will be in advance. That's fine, we just evaluate the expression at some point in this outside-in evaluation and support some of the below possibilities:asyncio.iscoroutine()
to test for this), which can then be scheduled onto an event loop.