Your own types, 1 of 8
Structs
Group fields into a value type with its own constructor and Methods, and see how it's copied.
What you’ll build
A Point type for a drawing program: a pair of coordinates with Methods to measure and move it.
A Struct is the right kind of type for it, since a point is a small value, like a number, that is
copied rather than shared.
Declaring a Struct
A Struct lists its fields with Field, each with its type and maybe a default. A Struct gets a
constructor that takes its fields in order, unless it declares a New of its own. Like any call,
it takes named arguments too. A field the call leaves out gets its default, or its type’s zero
when it has none.
Import std.core
Struct Point
Field X: Float
Field Y: Float = 0.0
End Struct
Local a = Point(3.0, 4.0)
Local b = Point(Y: 2.0, X: 1.0)
Local c = Point(5.0)
Print(a.X, a.Y, b.Y, c.Y)
Print("{a:?}")3 4 2 0
Point { X: 3, Y: 4 }{a:?} shows any value in its debug form, with each field’s name and value.
Methods
A Method is a function that belongs to the type. Inside it, the fields are used by name. A
Struct’s Methods only read its fields; a ByRef Method can change them, and can only be called
on a variable, whose value it changes in place.
Import std.core
Import std.math
Struct Point
Field X: Float
Field Y: Float
Method Length(): Float => Sqrt(X * X + Y * Y)
ByRef Method Move(dx: Float, dy: Float)
X += dx
Y += dy
End Method
End Struct
Local p = Point(3.0, 4.0)
Print(p.Length())
p.Move(1.0, -1.0)
Print(p.X, p.Y)5 4 3
Sqrt is from std.math.
Copies
A Struct is a value: assigning it, passing it to a function, or storing it in an array makes a
copy. Changing the copy leaves the original as it was. == compares two Structs field by field.
Import std.core
Struct Point
Field X: Float
Field Y: Float
ByRef Method Move(dx: Float, dy: Float)
X += dx
Y += dy
End Method
End Struct
Local start = Point(0.0, 0.0)
Local finish = start
finish.Move(5.0, 2.0)
Print("{start:?} {finish:?}")
Print(start == Point(0.0, 0.0), start == finish)Point { X: 0, Y: 0 } Point { X: 5, Y: 2 }
True FalseSince an array’s elements can move when it grows, a ByRef Method can’t be called on one in
place: points[0].Move(1.0, 1.0) is an error. Copy the element into a Local, change it, and
store it back.
Printing a Struct
Print and "{p}" show a value through its ToString Method, which a type gives by implementing
std.core’s Printable Interface. Without one, printing a Struct doesn’t build, and fb says what to
add; the debug form, {p:?}, always works.
Import std.core
Struct Point
Field X: Float
Field Y: Float
End Struct
Print(Point(1.5, 2.0))Compiling point.fb point.fb:8:7: error: Point can't be shown by 'Print'; implement Printable, with a ToString | 8 | Print(Point(1.5, 2.0)) | ^^^^^^^^^^^^^^^ error: couldn't build point.fb because of 1 error
With Implements Printable and a ToString, it prints:
Import std.core
Struct Point Implements Printable
Field X: Float
Field Y: Float
Method ToString(): String => "({X}, {Y})"
End Struct
Local path = [Point(0.0, 0.0), Point(1.5, 2.0), Point(3.0, 0.5)]
Print(path[1])
Print(path)(1.5, 2) [(0, 0), (1.5, 2), (3, 0.5)]
What you learned
- A
Structis a value type made of fields, with a constructor that takes them in order; a field left out gets its default or its zero. - Methods read the fields by name; a
ByRef Methodchanges them in place. - Assigning a Struct copies it, and
==compares its fields. Implements Printableand aToStringMethod let a Struct be printed.
The rules are in the language reference.
Report an issue with this page or with FutureBlitz on GitHub.