This is a simple Java implementation of generators, that resemble those found in the Python language. They are just generators (that is, a convenient way to create iterators), not full coroutines.
Here are some examples that show how Python generators can be translated into Java Jenerators.
- Generate all integer values.
- Python
def integers(): i = 0 while True: yield i i += 1 it = integers() print(next(it)) print(next(it)) print(next(it))
- Java
var integers = new Jenerator<Integer>(yield -> { for (int i = 0; ; ++i) yield.accept(i); }); var it = integers.iterator(); System.out.println(it.next()); System.out.println(it.next()); System.out.println(it.next());
- Output
0 1 2
- Python
- Generate the truth table of size n.
- Python
def truth_values(n): a = [True] * n def go(i): if i == 0: yield a else: a[n - i] = True yield from go(i - 1) a[n - i] = False yield from go(i - 1) return go(n) for a in truth_values(3) print(a)
- Java
Function<Integer, Jenerator<boolean[]>> truthValues = n -> new Jenerator<>(yield -> { boolean[] a = new boolean[n]; var go = new Consumer<Integer>() { public void accept(Integer i) { if (i == 0) { yield.accept(a); } else { a[n - i] = true; this.accept(i - 1); a[n - i] = false; this.accept(i - 1); } } }; go.accept(n); }); for (var a : truthValues.apply(3)) System.out.println(Arrays.toString(a));
- Output
[true, true, true] [true, true, false] [true, false, true] [true, false, false] [false, true, true] [false, true, false] [false, false, true] [false, false, false]
- Python
- Generate all combinations of k elements from list x.
- Python
def gcomb(x, k): if k > len(x): return if k == 0: yield [] else: first, rest = x[0], x[1:] for c in gcomb(rest, k - 1): c.insert(0, first) yield c for c in gcomb(rest, k): yield c seq = list(range(1, 5)) for k in range(len(seq) + 2): print(f"{k}-combs of {seq}:") for c in gcomb(seq, k): print(" ", c)
- Java
<T> Jenerator<List<T>> gComb(List<T> x, int k) { return new Jenerator<>(yield -> { if (k > x.size()) return; if (k == 0) yield.accept(new LinkedList<>()); else { var first = x.getFirst(); var rest = x.stream().skip(1).toList(); for (var c : gComb(rest, k - 1)) { c.addFirst(first); yield.accept(c); } for (var c : gComb(rest, k)) yield.accept(c); } }); } var seq = IntStream.range(1, 5).boxed().toList(); IntStream.range(0, seq.size() + 2).forEach(k -> { System.out.printf("%d-combs of %s%n", k, seq); for (var c : gComb(seq, k)) System.out.println(" " + c); });
- Output
0-combs of [1, 2, 3, 4] [] 1-combs of [1, 2, 3, 4] [1] [2] [3] [4] 2-combs of [1, 2, 3, 4] [1, 2] [1, 3] [1, 4] [2, 3] [2, 4] [3, 4] 3-combs of [1, 2, 3, 4] [1, 2, 3] [1, 2, 4] [1, 3, 4] [2, 3, 4] 4-combs of [1, 2, 3, 4] [1, 2, 3, 4] 5-combs of [1, 2, 3, 4]
- Python