Support from Haxe 3.4
to 4.3
This library adds the yield
metadata, which is similar to the yield
keyword in C#.
The yield
metadata defines iterator blocks and indicates that the function, operator (see operator overloading), or accessor in which it appears is an iterator.
When defining an iterator with yield
statements, an extra class is implicitly created to hold the state for an iteration likewise implementing the Iterator<T> or Iterable<T> pattern for a custom type (see iterators for an example).
Any @yield
expressions are available for classes that are annotated with the :yield
metadata, or available for all classes that extend classes annotated with :yield(Extend)
.
@:yield
class MyClass {
// ...
}
The following example shows the two forms of the yield
metadata:
@yield return expression;
@yield break;
Use @yield return
to return each element one at a time.
Use @yield break
to end the iteration.
Iterator methods can be run through using a for
expression or Lambda functions. When @yield return
is reached in the iterator method, expression
is returned. Execution is restarted from that location the next time that the iterator function is called.
The return type must be Iterator<T> or Iterable<T>. If no return type is defined, the type will be Dynamic, and can be unified to both Iterator or Iterable.
Here’s an example of the yield
metadata usage:
@:yield
class Test {
function sayHello (name:String):Iterator<String> {
@yield return “Hello”;
@yield return name + “!”;
}
}
Here the sayHello function usage:
for (word in sayHello(“World”)) {
trace(word); // “Hello”, “World!”
}
Call the sayHello method returns an Iterator<String>. The body of the method is not executed yet.
The for
loop iterates over the iterator while the Iterator<String>.hasNext
method returns true.
The method Iterator<String>.hasNext
executes only once the body of sayHello until the next @yield
expression is reached.
In case of a @yield return
, Iterator<String>.hasNext
will return true, and the result of the execution can be get once by calling Iterator<String>.next
.
The Iterator<String>.next
method can also be used without calling Iterator<String>.hasNext
. If the end of sayHello is reached, Iterator<String>.next
returns the default value of the return type.
Here’s a second example:
function getCounter ():Iterator<UInt> {
var i:UInt = 0;
while (true) {
@yield return i++;
}
}
var counter:Iterator<UInt> = getCounter();
counter.next(); // 0
counter.next(); // 1
counter.next(); // 2
// ...
counter.next(); // n
You can compile with some haxe compilation parameters (or pass several yield.YieldOption
into the :yield
metadata):
-
yield-extend
If the option is enabled, all extending classes will be able to use@yield
expressions. If this option affects an interface, all implementing classes and all extending interfaces will be able to use@yield
expressions. This is disabled by default. Compile with-D yield-extend
. -
yield-explicit
If the option is enabled, the return type of iterative functions needs to be explicitly specified. This is disabled by default. Compile with-D yield-explicit
. -
yield-keyword
Use a custom keyword instead of "yield". Compile with-D yield-keyword=myCustomMetaName
. -
yield-parse
Specifies packages or classpaths to include in the yield parser. All the impacted classes will no longer need to be annotated with:yield
to be able to use the@yield
expressions. This can be recursive using the*
wildcard. Compile with-D yield-parse= my.package.one, my.packages.*, my.class.Foo
. -
yield-types
Specifies types which automatilally trigger the yield parser when imported. Compile with-D yield-types= foo.Bar, foo.Bar.Subtype
. Available from init-macros throughyield.parser.Parser.parseOnImport
. -
yield-position-mapping
Gives more accurate positions when an exception arises. This is the default behavior in debug mode only when using Haxe 4.1 or above. It can be disabled with-D no-yield-position-mapping
. Compile with-D yield-position-mapping
to enforce this behavior in release mode too.
-
yield.parser.Parser.parseOnImport
Similar to-D yield-types=some.Type
. -
yield.parser.Parser.onYield
Adds a callback which allows transforming each yielded expression.See the coroutine library for an example. You can also browse the unit tests.
To install the library, use haxelib install yield
and compile your program with -lib yield
.
-
To clone the github repository, use
git clone https://github.com/dpomier/haxe-yield
-
To tell haxelib where your development copy is installed, use
haxelib dev yield my/repositories/haxe-yield
To return to release builds use haxelib dev yield
To help to debug a specific function, you can use the haxe compilation parameter -D yield-debug= myFunctionName
to see the result after the parsing is done.
Other libraries addressing generators:
- https://github.com/Aurel300/pecan - Macro-based library that lets you write coroutines with input/output and goto support.
- https://github.com/RealyUniqueName/Coro - Haxe compiler plugin which adds generic coroutines implementation (including built-in async/await and generators)
- https://lib.haxe.org/p/tink_await/ - Adds async/await for tink_core futures
- https://github.com/haxe-continuation/haxe-continuation - Adds async/await
- https://lib.haxe.org/p/moon-core/ - Utility library which includes generator functions, fibers, yield and await