nadako / haxe-coroutines

41 stars 5 forks source link

Syntax #1

Closed nadako closed 6 years ago

nadako commented 7 years ago
async function loadXml(url) {
    return Xml.parse(await loadString(url));
}

To support that we introduce new keywords: async and await, a new Expr node: EAwait(e:Expr) and the isAsync flag for the Function structure.

RealyUniqueName commented 7 years ago

Should it be keywords? Maybe meta is preferable since it can hold some additional info e.g. for cps.

nadako commented 7 years ago

Not sure, meta for compiler features always look weird IMO.

Anyway, right now I'm also considering Kotlin-style coroutines that don't actually require much new syntax and maybe can indeed be triggered by meta at least at first.

nadako commented 7 years ago

So, after some research, I think I like the Kotlin approach more. They have the "suspending" function modifier and calling functions with this modifier means that the current coroutine should be paused. It's more generic and doesn't require explicit await syntax, which can be nice for DSLs. Also the fact that the compiler knows that there's a suspending call, eliminates potential bugs when someone forgets to await a function when its result value is unused.

The original example could look like this:

suspend function loadXml(url) {
    return Xml.parse(loadString(url)); // loadString is suspending, so the execution will be paused
}

suspend function loadString(url) { ... }

Here's a fully working demonstration: https://gist.github.com/nadako/8761a0767654dd28c8a636d84ea399e8

RealyUniqueName commented 7 years ago

I don't like there is no syntax which will notify reader about "suspend points".

nadako commented 7 years ago

I don't like there is no syntax which will notify reader about "suspend points".

I think in real world, the function like the loadString above would return some kind of future/promise/task, and to await it there'll be a suspending await method, which is quite straightforward to read IMO:

suspend function loadXml(url) {
    return Xml.parse(loadString(url).await()); // or await(loadString(url))
}

The benefit of not having await hard-baked into the language itself is that it can be used for DSLs for e.g. UIs or in-game cutscenes, where everything is async and you'd have to write await everywhere and the code would become very cluttered.

Another benefit is that await have a single meaning - we await for execution of some task, while there can also be yield - we just yield control returning some value (generators), or channel.send (go-like concurrency). Kotlin approach supports all these by implementing very basic suspendable functions which then others can build on.

RealyUniqueName commented 7 years ago

Looks nice at first sight.

nadako commented 6 years ago

Alright, I pushed whatever I had in a Gist as README and will continue to clear syntax-related things up there.