This is a specialization of the initial proposal that only works on tasks. It introduces the keywords async
and await
.
async
let
_ = await print 3
_ = await print 4
in
await print 5
The idea is that you can put the await
keyword anywhere under an async, as long as you do not cross into a closure. Here are some more examples.
getPeople : Task Http.Error (List Person)
getPeople =
async
let
olds = await get (list person) oldPeopleUrl
youngs = await get (list person) youngPeopleUrl
in
olds ++ youngs
getPeople' : Task Http.Error (List Person)
getPeople' =
async
await get (list person) oldPeopleUrl ++ await get (list person) youngPeopleUrl
- Exists in C# and is proposed for ES7
- You can be more flexible about where you put
await
indicators - We can do
(mb = await mailbox)
in the main module - It rules out all the crazy / questionable stuff we were doing with JSON, XML, Maybe, etc.
- No general purpose thing for now, no need to explicitly think about
andThen
,andMap
, etc.
- The path to making this generic is much trickier
- We do not cover the Haxl case
I think my biggest concern here is how we'll support Haxl, or other clever things that might come along. Maybe we could have something like the "programmable let" thing like this:
@async haxl
await get (list person) oldPeopleUrl
++ await get (list person) youngPeopleUrl
And that'd do the same sort of rewriting we were talking about with "programmable let". The trouble is that it looks sort of goofy for things that are not asynchronous.
add : Maybe Int -> Maybe Int -> Maybe Int
add mx my =
@async maybe
await mx + await my
Maybe that is fine? Maybe it'll be easier to cross this bridge once tons of people understand async/await?
One crucial detail is that if you define a function or a lambda, you cannot use await
in the body unless it also is paired with another async
. So here's something that is NOT allowed:
-- THIS DOES NOT WORK!!!
getPeople : Task Http.Error (List PersonSummary)
getPeople =
async
let
summary person =
await get summary (urlFor person)
olds = await get (list person) oldPeopleUrl
youngs = await get (list person) youngPeopleUrl
in
map summary (olds ++ youngs)
I don't think it is possible to make the types work out here. Here are two fixed versions.
getPeople : Task Http.Error (List PersonSummary)
getPeople =
async
let
summary person =
async
await get summary (urlFor person)
olds = await get (list person) oldPeopleUrl
youngs = await get (list person) youngPeopleUrl
in
await sequence (map summary (olds ++ youngs))
-- it is redundant to write "async await" right next to each other
-- so we can simplify to this
getPeople : Task Http.Error (List PersonSummary)
getPeople =
async
let
summary person =
get summary (urlFor person)
olds = await get (list person) oldPeopleUrl
youngs = await get (list person) youngPeopleUrl
in
await sequence (map summary (olds ++ youngs))