Hello. It would be great if there is @Generator annotation, which creates generator(lazily evaluated iterator). It already exists in many other languages like Javascript, Kotlin, Python, C#, etc. While it provides a way to create custom iterators easily, it is very hard to create manually.
I already have made working javac handler, feature page including detailed explanations, and tests in my fork.
https://github.com/storycraft/lombokHere is example code
@Generator
public static Iterable<Integer> range(int from, int to) {
for (int i = from; i < to; i++) {
yieldThis(i);
}
}
User can use yieldThis or yieldAll statement to yield values from generator. Calling hasNext or next method will resume generator until next yieldThis or yieldAll statement.
The handler converts method like below.
public static Iterable<Integer> range(int from, int to) {
class __Generator implements java.lang.Iterable<Integer>, java.util.Iterator<Integer> {
private int $state;
private Integer $nextVal;
private int gen238$i;
@java.lang.Override
public java.util.Iterator<Integer> iterator() {
return this;
}
@java.lang.SuppressWarnings("unchecked")
private <$THROW extends java.lang.Throwable>void __next() throws $THROW {
try {
while (true) switch ($state) {
case 0:
gen238$i = from;
case 1:
if (!(gen238$i < to)) {
$state = 8;
continue;
}
$state = 5;
$nextVal = gen238$i;
return;
case 5:
gen238$i++;
$state = 1;
continue;
case 8:
$state = 9;
case 9:
return;
default:
throw new java.lang.RuntimeException("Unreachable generator state");
}
} catch (final java.lang.Throwable t) {
$state = 9;
throw t;
}
}
@java.lang.Override
public boolean hasNext() {
if ($nextVal == null) this.<java.lang.RuntimeException>__next();
return $nextVal != null;
}
@java.lang.Override
public Integer next() {
if ($nextVal == null) {
this.<java.lang.RuntimeException>__next();
if ($nextVal == null) throw new java.util.NoSuchElementException("Called next on finished generator");
}
try {
return $nextVal;
} finally {
$nextVal = null;
}
}
}
return new __Generator();
}
So user can use range method like this
for (int i : range(0, 5)) {
System.out.println(i);
}
This code prints
0
1
2
3
4