Cω - Samples

Choice Types Tutorial

This tutorial shows how to create and use the choice types in a simple program. The program can be compiled using the Cω compiler.

Sample Files

To run this tutorial, you may use the following project and source files:

These files are located in the \samples\Basics\Address subdirectory under the path where you installed Cω, which by default is C:\Program Files\Comega.

Tutorial

XSD content models also allow the use of choice elements <choice>, or | in DTDs. In Cω we can express these using choice types. For example, we can use a choice type to define an Address that allows either a Street or a POBox:

struct Address {
  struct{
    choice { string Street; int POBox; };
    string City;
    int? ZipCode;
    string Country;
  };
}

The type choice{ string Street; int POBox; } captures the fact that an Address can either contain a string Street; or an int POBox; member, but not both.

Member access over choice types gives rise to an interesting question about the result type. Given an instance of type Address, what should the types be for accessing a.POBox and a.Street be? Since an instance a of type Address can either contain a Street member of type string or a POBox member of type int, accessing a.Street will either return a string when a does contain a Street member, or null when a does not contain a Street member and similarly, when a contains a POBox member, accessing a.POBox returns an int, and when a does not contain a POBox member, it returns null. Optional types solve this dilemma: the type of a.Street becomes string?, and the type of a.POBox becomes int?.

Now what should be the result type of the query a.* that selects all the members of the instance a of type Address. Wild-card selection a.* is shorthand for the following generator expression:

{ yield return a.Street; yield return a.POBox ; yield return a.City; yield return a.ZipCode; yield return a.Country; }
            
that yields the stream "One Microsoft Way", "Redmond", 98052, "US", provided we are using it to yield a business street address for Microsoft. The returned stream elements are either of type string or of type integer, and any nulls are discarded. In Cω, the result type is thus a stream containing strings and integers choice{int;string;}*.

Example

The following is a complete Cω program that demonstrates using the choice types of Cω as discussed above.

using System;
using System.IO;
using Microsoft.Comega;

struct Address {
  struct{
    choice { string Street; int POBox; };
    string City;
    int? ZipCode;
    string Country;
  };
}

public class Test {

    public static void Main() {
      a = <Address>
            <Street>One Microsoft Way</Street>
            <City>Redmond</City>
            <Country>USA</Country>
          </Address>;
      
      // get Street
      string? b = a.Street;
      foreach(it in b){ Console.WriteLine("Street = {0}", it); };
      //get POBox
      int? c = a.POBox;
      foreach(it in c){ Console.WriteLine("POBox = {0}", it); };
      // Serialize whole thing
      StringWriter sw = new StringWriter();
      new XmlSerializer(typeof(Address)).Serialize(sw,a);
      Console.WriteLine(sw.ToString());

      System.Console.ReadLine();
    }

}

Output

Street = One Microsoft Way
<Address>
  <Street>One Microsoft Way</Street>
  <City>Redmond</City>
  <Country>USA</Country>
</Address>