Next: , Previous: , Up: Structs   [Contents][Index]


17.5.7 Field Initializers

We saw that field constraints are useful to express magic numbers, which are pretty common in binary formats. Imagine a package has a marker byte at the beginning, which should always be 0xff. We could use a constraint like in:

type Packet =
  struct
  {
    byte marker : marker == 0xff;
    byte length;
    byte[length] payload;
  };

This works well when mapping packages. The constraint is checked and a constraint violation exception is raised if the first byte of the alleged package is not 0xff.

However, suppose we want to construct a new Package, with no particular contents. We would use a constructor, but unfortunately:

(poke) Packet { }
unhandled constraint violation exception

What happened? Since we didn’t specify a value for the marker in the struct constructor, a default value was used. The default value for an integral type is zero, which violates the constraint associated with the field. Therefore, we would need to remember to specify the marker, every time we construct a new packet:

(poke) Packet { marker = 0xff }
Packet {
  marker=0xffUB,
  length=0x0UB,
  payload=[]
}

Unfortunately, such markers and magic numbers are not precisely very memorable. To help with this, Poke has the notion of type field initializers. Let’s use one in our example:

type Packet =
  struct
  {
    byte marker = 0xff;
    byte length;
    byte[length] payload;
  };

Note how the syntax is different than the one used for constraints. When a field in a struct type has an initializer, two things happen:

This achieves exactly what we want, in a very natural way:

(poke) Packet {}
Packet {
  marker=0xffUB,
  length=0x0UB,
  payload=[]
}

It is possible to specify both a constraint and an initializer in the same field. Suppose we want to support several kinds of packets, characterized by several markers. The supported markers are however a closed set. We could do it like this:

type Packet =
  struct
  {
    byte marker = 0xff : marker in [0xffUB, 0xfeUB];
    byte length;
    byte[length] payload;
  };

Note also that it is considered good practice to design struct types in a way that a constructor with no arguments will result in something usable.


Next: , Previous: , Up: Structs   [Contents][Index]