ExpandCollapsePrev Next Index

+ 16.1 Structs

You can also have named structures as in C:

  struct X {
    a:int;
    b:double;
  };
  var x:X = X(1,2.2);
  println$ str x.a + str x.b;

Each struct has an autogenerated constructor which takes a tuple of values of types in the same order as declared in the struct definition.

Whilst structs are similar to records, records are structurally typed, or anonymously typed. This means you can just create a value of a record type, without declaring the type.

For a struct however, you must first declare the type and give it a name: they're said to be nominally typed. This means two structs with the same components but declared with distinct names are distinct types.

+ 16.1.1 Accessor Methods

You can also define functions in a struct like this:

  struct complx {
    x: double;
    y: double;
    fun arg => tan (self.x/self.y);
    fun mod => sqrt (self.x * self.x + self.y * self.y);
    fun add (z:complx) => complx(self.x + z.x, self.y + z.y);
  }
  
  var z = complx(0.5, 0.5);
  println$ z.x, z.y, z.arg, z.mod;
  
  var a = z.add z;
  println$ a.x, a.y;

Accessor functions are ordinary function which just get an extra argument called self of the type of the struct.

+ 16.1.2 Mutator Methods

You can also define mutators in a struct.

  struct complx2 {
    x: double;
    y: double;
    proc doset (xx:double, yy:double) { self.x <- xx; self.y <- yy; }
  }
  
  var b = complx2(1.0,2.0);
  (&b).doset (0.7, 0.8);
  println$ b.x, b.y;

Note that mutators require a pointer argument.

To make it easier, to work with fields and pointers Felix provides two special syntax sugars:

    Sugar       Meaning
    -------     ----------
    p*.mem      (*p).mem
    v&.mem      (&v).mem
    v = x;      (&v) <- x;