Tagged Unions

A tagged union declaration looks just like a C union, except that it you must specify the @tagged qualifier when declaring it. For example:

   @tagged union Foo {
      int i;
      double d;
      char *@fat s;

The primary difference with C unions is that a tagged union includes a hidden tag. The tag indicates which member was last written. So, for example:

  union Foo x;
  x.i = 3;
  x.s = "hello";

causes the hidden tag to first indicate that the i member was written, and then is updated to record that the s member was written.

When you attempt to read a member of a tagged union, a check is done on the hidden tag to ensure that this was the last member written, and thus the union contains a valid object of that member’s type. If some other member was last updated, then a Match_Exception will be thrown.

You can test the hidden tag of a tagged union by using the tagcheck operation. For example:

  void printFoo(union Foo x) {
    if (tagcheck(x.i))
    else if (tagcheck(x.d))
    else if (tagcheck(x.s))

Alternatively, you can use pattern matching (described in the next section) which will ensure that you cover all of the cases properly. For instance, the function above may be rewritten as:

  void printFoo(union Foo x) {
    switch (x) {
    case {.i = i}: printf("%d",i); break;
    case {.d = d}: printf("%g",d); break;
    case {.s = s}: printf("%s",s); break;

If we failed to leave out one of the cases in the pattern match, then the compiler would warn us. This is particularly helpful when you add new variants to a tagged union, for then the compiler pinpoints the spots that you need to update in your code. Therefore, we encourage the use of pattern matching where possible.