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;