2011-07-09

Generators in Vala

Hello,
here I'll show a cool snippet code making use Vala async functions for emulating Python/Ruby generators. Creating a generator is as simple as extending the Generator class and implementing the generate() method.

abstract class Generator<G> {
private bool consumed;
private G value;
private SourceFunc callback;

public Generator () {
helper ();
}

private async void helper () {
yield generate ();
consumed = true;
}

protected abstract async void generate ();

protected async void feed (G value) {
this.value = value;
this.callback = feed.callback;
yield;
}

public bool next () {
return !consumed;
}

public G get () {
var result = value;
callback ();
return result;
}

public Generator<G> iterator () {
return this;
}
}

class IntGenerator : Generator<int> {
protected override async void generate () {
for (int i=0; i < 10; i++) {
yield feed (i);
}
}
}

void main () {
var gen = new IntGenerator ();
foreach (var i in gen) {
message ("%d", i);
}
}


You can find the above code snippet here as well.

4 comments:

  1. This should be extended to allow something like "yield return" in C#!!! :)

    ReplyDelete
  2. @Martin That needs special library support, like Enumerable or Iterable or something like that. And anyway the above code isn't that huge/ugly to copy&paste ;)

    ReplyDelete
  3. Doesn't compile with vala-0.12.0

    valac --pkg gio-2.0 --save-temps generator.vala
    ./generator.c: In function ‘generator_feed’:
    ./generator.c:250:57: error: ‘g_dup_func’ undeclared (first use in this function)
    ./generator.c:250:57: note: each undeclared identifier is reported only once for each function it appears in
    error: cc exited with status 256
    Compilation failed: 1 error(s), 0 warning(s)

    ReplyDelete
  4. I think latest vala 0.13 (or even master) is necessary.

    ReplyDelete