[Vala] Puzzled about Gee HashMap and iterating over it with foreach



The below test case has me slightly baffled. Probably I'm just being extraordinarily dense, and if someone someone enlighten me as to why 'foreach (var f in hashmap)' seems to get V typed f (rather than Entry<K,V>), and a faulty iterator at that, I'd be very grateful. (the toy hash function is just for testing).

Also, the Vala tutorial says "For strings and integers the hash and equal functions are detected automatically". However I found this isn't the case, at least if you try to use an integer as the key. It seems to treat integers as (int *), and a Glib int hash func that expects a (ginteger *) and then obviously a crash when it tries to dereference it. Hence why I had to supply hash data and key funcs. Can give more details if that isn't a known problem.

public class Foo : Object {
  public int id { get; construct; }

  public Foo (int id) {
    Object (id : id);
  }
}

public static int main (string[] args) {

  HashFunc keyfunc = (a) => { return ((uint)a & 0xffff); };
  EqualFunc eqfunc = (as1, as2) => { return (as1 == as2); };

  var foos = new Gee.HashMap<int, Foo> (keyfunc, eqfunc);

  for (int i = 1; i < 4; i++) {
    var f = new Foo (i);
    stdout.printf ("set %p:%d\n", f, f.id);
    foos.set (i, f);
  }

  stdout.printf ("foos %p, size %d\n", foos, foos.size);
  stdout.printf ("foos has: \n");

  stdout.printf ("(using foos.values)\n");
  foreach (Foo f in foos.values) {
    stdout.printf ("%p:%d\n", f, (f != null) ? f.id : 0);
  }

  // According to the Gee 0.7 documentation, and my local 0.6.1-3.fc16
  // VAPI, and the Vala tutorial, iterating with foreach over the bare
  // object should use the method from the iterable interface. For 0.6.1
  // the AbstractMap VAPI declares it as:
  //
  // Gee.Iterable<Gee.Map.Entry<K,V>>
  //
  // and so the returned type for should be Gee.Map.Entry<int,Foo>.
  //
  // However valac 0.14.0 gives the following error trying to compile this:
  //
  // hashset-test.vala:31.3-31.44: error: Assignment: Cannot convert from `Foo' to `Gee.Map.Entry<int,Foo>'
  //   foreach (Gee.Map.Entry<int,Foo> e in foos) {
  //   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  //stdout.printf ("(iterate over foos)\n");
  //foreach (Gee.Map.Entry<int,Foo> e in foos) {
  //  Foo f = e.value;
  //  stdout.printf ("%d: %p:%d\n", e.key, f, (f != null) ? f.id : 0);
  //}

  // Given the VAPI definition, this shouldn't compile, and it shouldn't
  // work. However, given the error produced by the above, then this should
  // compile - and it does, without any warning.
  // However it doesn't work, as it prints out:
  //
  // set 0x1a78230:1
  // set 0x1a78290:2
  // set 0x1a782f0:3
  // foos 0x1a7c820, size 3
  // foos has:
  // (using foos.values)
  // 0x1a78230:1
  // 0x1a78290:2
  // 0x1a782f0:3
  // (iterate over foos, wrong way)
  // (nil)
  // 0x1a78230
  // 0x1a78290
  //
  // -----
  // Note the 'nil' and the missing entry.
  stdout.printf ("(iterate over foos, wrong way)\n");
  foreach (Foo f in foos) {
    stdout.printf ("%p\n", f);
  }

  return 0;
}

--
Paul Jakma  paul jakma org  twitter: @pjakma  PGP: 64A2FF6A
Fortune:
Last yeer I kudn't spel Engineer.  Now I are won.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]