nadako / haxe-coroutines

41 stars 5 forks source link

Separate suspending functions and coroutine functions. #13

Closed RealyUniqueName closed 5 years ago

RealyUniqueName commented 5 years ago

This proposal implies that the suspending function and the coroutine function are the same.

suspend function load(url) {...}

suspend function getFirstLoaded(urlList) {
  var loaders = [];
  for(url in urlList) {
    //`load` is suspending. But `getFirstLoaded()` definitely should not be suspended here because no `await` applied.
    loaders.push(load(url));
  }
  //get the async operation, which will complete, when the first of the loaders will complete.
  var any = AsyncUtils.whenAny(loaders)
  //here is where the suspension should happen
  return any.await();
}

I think these concerns should be separated.

RealyUniqueName commented 5 years ago

Here are some suggestions for coroutine functions:

  1. coroutine keyword instead of function keyword for the full function syntax and add coroutine to short lambdas:
    
    static coroutine add(a:Int, b:Int) {
    return a + b;
    }

coroutine (a, b) -> a + b;


2. `coro` accessor:
```haxe
coro static function add(a:Int, b:Int) {
  return a + b;
}

coro (a,b) -> a + b;
RealyUniqueName commented 5 years ago

And of course one function could be both coroutine and suspending:

suspend static coroutine add(a:Int, b:Int) ...
//or
suspend coro static function add(a:Int, b:Int)...
nadako commented 5 years ago

The original message is mixing concepts, because load should NOT be suspending in this example. Instead it should return some kind of async task abstraction (like promise), that can then be awaited using a suspending function or collected into array and combined into other task abstraction value to be awaited, like it's done in that example.

So I don't understand the need for two different keywords. Feel free to open another issue with a more fitting example if you disagree :)

RealyUniqueName commented 5 years ago

But what if my load is a coroutine itself? Now I have to create a wrapper non-coroutine function just to be able to not auto-start load if used inside of another coroutine.

// this will be autostarted if used inside of another coroutine
suspend function load(url:String) {
  var data = thirdPartyRequest(url).await();
  doSomething(data);
  return data;
}

//now I need to use this to avoid atuostart `load`
function loadHuh(url):Promise<String> {
  return load(url);
}
nadako commented 5 years ago

But what if my load is a coroutine itself?

You can (and have to) construct some kind of promise from your coroutine function, I described this exact use case with examples here: https://github.com/nadako/haxe-coroutines/blob/master/README.md#local-suspending-functions. Whether it's started automatically or on the first await is up to the promise implementation.