pecan

Input and output

Coroutines can accept() inputs and yield(...) outputs. To ensure type safety, the types for inputs and outputs must be declared as part of the co macro call (see declaration).

Input

Within coroutine code, accept() can be used to accept input of the declared type. The call suspends the coroutine until the value is available.

Example: accept() usage

var greeter = pecan.Co.co({
  trace('Hello, ${accept()}, from ${accept()}!');
}, (_ : String)).run();
greeter.give("Haxe");
greeter.give("pecan"); // output: Hello, Haxe, from pecan!

All accept() calls within an expression are evaluated before the expression itself. The evaluation order of complex expressions involving calls to accept() and other functions may therefore be different than expected. Boolean operators with accept() will not short-circuit.

Output

Within coroutine code, yield(...) can be used to provide output from the coroutine. The call suspends the coroutine until the value is taken.

Example: yield(...) usage

var languages = pecan.Co.co({
  yield("Haxe");
  yield("Haxe 4");
}, null, (_ : String)).run();
trace('${languages.take()} is awesome!'); // output: Haxe is awesome!
trace('${languages.take()} is awesome!'); // output: Haxe 4 is awesome!

Custom input functions

It is possible to declare methods similar to accept. These methods must:

Functions declared this way can then be called from within coroutines, with the last two arguments filled in automatically. The second-to-last argument is how the custom input function provides the "real" return value.

The return value of the function is never used! It is only used for type inference. Returning null (or a default value on static targets) is recommended.

Unlike custom suspending functions, custom input functions always suspend the coroutine and always wake it up when the value is returned.

Example: delay that eventually returns a String

class Foobar {
  @:pecan.accept public static function acceptDelay(
    ms:Int,
    ?ret:String->Void,
    ?co:pecan.ICo<Any, Any, Any>
  ):String {
    haxe.Timer.delay(() -> ret("foo"), ms);
    return null;
  }
}

Usage:

pecan.Co.co({
  trace("Hello,");
  var x = Foobar.acceptDelay(1000);
  trace(x); // output: foo
}).run();
« Previous: Suspending calls Next: Labels »