reason
reason copied to clipboard
Built in syntax for async.
I've really liked Lwt's syntax for async (including the integration with try, let, and let + and for simultaneously async calls). We can bake this into Reason by default with something like let!, and then allow configuration of which library it should represent.
Imagine putting an attribute at the top of the file such as:
[@async Lwt];
or
[@async Async];
which could influence which library is used for that first class let binding syntax.
For the implementation, we could reuse Lwt's ppx plugin perhaps.
Syntax for monadic code will interact well with implicits: if you desugar
let! x = e in
let! y = e' in
return (g x y)
into
e >>= fun x ->
fun e' >>= fun y ->
return (g x y)
then you can just use implicits to pick the appropriate implementation of >>=.
Since the desugaring should be the same in any case, even without implicits you can write something like this
Lwt.(
let! x = e in
let! y = e' in
return (g x y)
)
to avoid the need for a magic attribute.
What would be the default? Optionals? That would be useful.
F# computation expressions are nice. You can specify the “builder” outside the let! block so you can have let! with different meaning in one file depending on the context.
Yes, I also think that the F# async ability to select the desired monad on a per-block rather than per-file basis is a significant benefit. Nesting them (essentially shadowing the outer let! by the inner one) also ought to work.
@gaearon That sounds like what I'm describing with attributes. You can put the "provider" of that asynchronicity at the to of the file, or even scoped to some lexical block, because you can place attributes anywhere in the tree.
Ah okay, I didn’t realize
you can place attributes anywhere in the tree
Ah okay, I didn’t realize
It's not obvious, and that doesn't mean it won't require some effort to replicate the nice scoping rules of lexical scoping.
We might be able to do it without attribute nodes in the AST, and instead just open the right module.
@yallop Have you seen Lwt's ppx extension? It seems to do that and much more (considers and bindings as being parallel, also unifies match/with with this same monadic concept). I am very much looking forward to modular implicits as well.
@jordwalke: I'm not that familiar with Lwt's ppx extension, but I know Jane Street's ppx_let, which does something similar (including parallel computation support for let ... and) and various other implementations. I think the important thing is to have two independent components:
- a way to desugar things like
letinto things like>>=. There are a few choices here (Lwt's ppx extension, ppx_let, ...) - a way to choose which
>>=to use in a particular block of code. This should be a separate step from desugaring and is best done via core language mechanisms such as local opens or implicits.
I'm probably missing some context here, but if ! means what I think it means, how would you express the following (which is valid using Babel/regenerator in JavaScript today) in Reason:
async function(): Promise<void> {
if (await someCall()) {
const [first, second] = Promise.all([thisReturnsAPromise(), thisAlsoReturnsAPromise()]);
}
}
I believe there was a proposal to add syntactic sugar for Promise.all() that died, which would have allowed for something like:
async function(): Promise<void> {
if (await someCall()) {
const [first, second] = await* thisReturnsAPromise(), thisAlsoReturnsAPromise();
}
}
See also #1321
i think that with my proposal, await can be an ordinary suspendable function. async can be an ordinary function that wraps a lambda in a promise. No need to create more syntax, since internal DSLs assembles language itself using functions. https://github.com/facebook/reason/issues/1982
let myAsyncFunc = async {
body
};
await @@ myAsyncFunc();
No need to reinvent the wheel, some languages already have the battle tested solution to this.
https://github.com/facebook/reason/issues/1982 internal DSLs + coroutines "aka suspendable functions".
This can probably be closed now that Reason supports OCaml's monadic/applicative let syntax, yes?