Structs¶
Definition¶
The struct construction introduces a nominally typed, or named product.
struct Point {
x: int;
y: int;
}
instance Str[Point] {
fun str (p:Point) =>
"Point(" + p.x.str + ", " + p.y.str + ")"
;
}
var p = Point (2,3);
println$ p.str;
Here, we note a Point consists of two integers, x and y, and we can make a Point by applying the type name Point to a pair of integers.
Also we provide an instance of the Str class with method str or type Point->string for converting a point to a human readable form. Str is a standard library class which is universally open.
Methods¶
Struct can have methods of two kinds: accessors and mutators. Here is an expanded version of Point:
struct Point {
x: int;
y: int;
fun norm => max (self.x, self.y);
proc reset { self.x <- 0; self.y <- 0; }
proc set (a:int, b:int) { self.x <- a; self.y <- b; }
}
var p = Point (1,2);
var y = p.norm;
p.set(p.x + 1, p.y + 1);
Accessors, with fun binder, implicitly get an extra parameter self of type Point. Mutators, with proc binder, implicitly get an extra parameter self of type &Point, a pointer to a Point.
Object Closures¶
In fact, these methods are ordinary functions and procedures. The nesting is just syntactic sugar for:
struct Point {
x: int;
y: int;
}
fun norm (self: Point) => max(self.x, self.y);
proc reset (self: &Point) { self.x <- 0; self.y <- 0; }
proc set (self: &Point) (a:int, b:int) { self.x <- a; self.y <- b; }
Because of this, the methods are higher order functions and we can form closures over objects of type Point:
var p = Point (1,2);
var setp = &p.set; // object closure
var resetp = { &p.reset; }; // object closure
setp (23,42);
println$ p.str;
resetp;
println$ p.str;
Note that &p.reset would call reset so we need to wrap the call in the general closure constructor {_}.