-
-
Notifications
You must be signed in to change notification settings - Fork 9
Structures
Structures allow for multiple data types to be combined together
Structures are declared by using the struct
keyword followed by a list of fields.
struct Employee (name String, age int, productivity float)
import basics
struct Tree (age int, height int)
func main {
tree Tree
tree.age = 12
tree.height = 43
print("tree.age => " + tree.age)
print("tree.height => " + tree.height)
}
tree.age => 12
tree.height => 43
Sometimes when declaring structures, multiple fields in a row will have the same type repeated for each of them.
struct Person (firstname String, lastname String, occupation String)
When this is the case, you can omit all of the repeated types expect the final one in order to simplify the definition.
struct Person (firstname, lastname, occupation String)
Sometimes it's desired to share the same fields as another struct. In order to make this easier, you can include fields of an already defined structure into a new one using the struct
keyword followed by the name of the structure.
struct Human (age int)
struct Citizen (struct Human, name String)
struct Doctor (struct Citizen, experience int, salary ulong)
If the included structure comes first in the field list, then the newly created structure will also be valid as the included structure when taken as a pointer and casted.
import basics
struct Point2D (x, y float)
struct Point3D (struct Point2D, z float)
func distanceToOrigin(p Point2D) float {
return sqrtf(p.x * p.x + p.y * p.y)
}
func main {
point Point3D
point.x = 3.0f
point.y = 4.0f
point.z = 2.0f
xy_distance float = distanceToOrigin(*cast *Point2D &point)
print("2D distance to origin => " + xy_distance)
}
2D distance to origin => 5.0
Structure definitions can optionally be followed by a structure domain, in which all function declarations inside will be made into methods
import basics
struct Person (firstname, lastname String) {
func getFullname String {
return this.firstname + " " + this.lastname
}
}
func main {
person Person
person.firstname = "Isaac"
person.lastname = "Shelton"
print("Person's name is: " + person.getFullname())
}
Person's name is: Isaac Shelton
By default, structures contain padding in order to improve access performance.
This can be disabled using the packed
keyword.
packed struct MyFileHeader (magic ushort, version uint, offset1, offset2 usize)
Records are structures that the compiler will automatically generate a constructor for.
Records are usually preferrable for holding data over regular structures.
record Person (firstname, lastname String, age int)
func main {
person Person = Person("Bekah", "Armstrong", 19)
printf("%S %S is %d years old\n", person.firstname, person.lastname, person.age)
}
See records for more information
Structure types can also be used anonymously without a name
import basics
import math
func main {
point struct (x, y, z float)
point.x = 1.0f
point.y = 2.0f
point.z = 3.0f
printf("Distance to origin is %hf\n", distanceToOrigin(point))
}
func distanceToOrigin(p struct (x, y, z float)) float {
return sqrt(p.x * p.x + p.y * p.y + p.z * p.z)
}
In order for two anonymous structure types to be considered compatible, they must have the same fields and the same structural layout.
For example:
The types struct (x, y float)
and
struct (u, v float)
are incompatible.
And also the types
struct (a, b int)
and
struct (b, a int)
are incompatible.
Structs and unions can be used as anonymous wrappers for fields.
struct FloatOrIntVec3 (
is_floats bool,
union (
struct (xf, yf, zf float),
struct (xi, yi, zi int)
)
)
In the above example, the type FloatOrIntVec3
has 7 fields, some of which overlap in memory:
is_floats
xf
yf
zf
xi
yi
zi
However there's an anonymous union of two anonymous structs, which are unnamed, so the names of the sub fields are promoted to be directly accessible from the next higher name scope.
Because of this, we can access members like xf
directly instead of having to go through a field.
struct FloatOrIntVec3 (
is_floats bool,
union (
struct (xf, yf, zf float),
struct (xi, yi, zi int)
)
)
// Can access 'xf' via 'this.xf' where 'this' is a '*FloatOrIntVec3'
// since the union field is unnamed and also the struct field of type `struct (xf, xy, xz float)` is unnamed
versus
struct FloatOrIntVec3 (
is_floats bool,
data union (
float_info struct (xf, yf, zf float),
int_info struct (xi, yi, zi int)
)
)
// We have to access 'xf' via 'this.data.float_info.xf' (where 'this' is a '*FloatOrIntVec3')
// since the union field 'data' is named and also the struct field 'float_info' is named
Classes are structures which can have virtual methods defined on them.
import basics
class Shape () {
constructor {}
virtual func getArea() float = 0.0
}
class Rectangle extends Shape (w, h float) {
constructor(w, h float){
this.w = w
this.h = h
}
override func getArea() float = this.w * this.h
}
func main {
shape *Shape = new Rectangle(5, 10)
defer delete shape
print(shape.getArea())
}
See classes for more information.