15:25
<jschoi>
Well, they wouldn’t add keywords so much as override the semantics of several existing keywords (like yield, await, return) within the decorated blocks. But yeah!
15:28
<Mathieu Hofman>
Interesting. Just within that context tho, right? Not nested calls for example.
15:34
<jschoi>
Interesting. Just within that context tho, right? Not nested calls for example.

Yes, that’s right.

I was rewriting a plan in https://gist.github.com/js-choi/854ccbc34787c697ea1f8458d6a1d660, but it was in the middle of a rewrite (most of the stuff is hidden in the Scratchpad’s <details> element at the end), then I lost the bandwidth to work on it.

15:35
<jschoi>
One big thing that blocked me was the unresolved question on whether do expressions will use implicit-result block semantics (return works on the outer function), explicit-result block semantics (same except the final statement is the final evaluation result), or IIFE semantics (return is required and works on the inner function). Context blocks / decorated blocks would have to use IIFE semantics, so if do blocks do not go with IIFE semantics then they can’t use the do keyword.
15:36
<jschoi>
The papers in http://tomasp.net/academic/papers/computation-zoo/ give a nice overview of the general ideas from the F# perspective (although they use a little of the usual higher-level FP jargon that we definitely would avoid).
16:09
<rbuckton>
Well, they wouldn’t add keywords so much as override the semantics of several existing keywords (like yield, await, return) within the decorated blocks. But yeah!
F# computations did both, and can also leverage a type system to acquire an AST for an expression to do tree rewrites to convert a local computation expression into a remotely executed operation (such as in a SQL database).
16:10
<rbuckton>
One big thing that blocked me was the unresolved question on whether do expressions will use implicit-result block semantics (return works on the outer function), explicit-result block semantics (same except the final statement is the final evaluation result), or IIFE semantics (return is required and works on the inner function). Context blocks / decorated blocks would have to use IIFE semantics, so if do blocks do not go with IIFE semantics then they can’t use the do keyword.
I've always been concerned that do expressions don't have an explicit return from the block, even if it's not return per se.
16:12
<rbuckton>

I was playing around with what this might look like:

// given:
//
//  @expr do {
//      console.log("a");
//      yield 1;
//      console.log("b");
//  }
//
// translates to:
//
expr.run(
    expr.delay(() => {
        console.log("a");
        return expr.combine(
            expr.yield(1),
            expr.delay(() => {
                console.log("b");
                return expr.zero();
            })
        );
    })
);
17:14
<jschoi>

Yeah, pretty much like that.

Userland would be able to do async do blocks and beyond with a unified syntax. Though they would use do only if do blocks use IIFEs; that’s why the Gist uses @context in { … }.

17:15
<jschoi>
F# computations did both, and can also leverage a type system to acquire an AST for an expression to do tree rewrites to convert a local computation expression into a remotely executed operation (such as in a SQL database).
Someday we might have a JS AST in the language itself that the context block could use at runtime—all without needing a full macro system. But that would be a future-compatible extension.
17:15
<jschoi>
I know you want those LINQ blocks, haha.
19:34
<rbuckton>
I don't know. F# computation expressions don't feel as fluid to me as FLWOR/FLWOS syntax, and the ability to introduce arbitrary "keywords" inside such a block isn't great for static analysis. That said, being able to add a distinct or count in a F# query expression is an improvement over C#'s LINQ syntax