Enums
A set of named integers, with a type of its own:
import "std/io"
enum Kind u8 { None Bool Text = 9 Real}
func describe(k Kind) string { switch k { case Kind.None: return "nothing" case Kind.Bool: return "a flag" case Kind.Text: return "a string" case Kind.Real: return "a number" }}
func main() !int { try io.Print(describe(Kind.Text)) return 0}Look at what is not in that switch: a default. It is not needed, and that is
the point of naming the set. A switch over an enum with no default has to
cover every member, so the function returns on every path and the compiler
knows it. Add a member later and every switch that has stopped being complete
tells you where:
error: this switch over Kind does not cover Bytesnote: add the missing cases, or a 'default'The width is optional — enum Kind u8 above, enum Kind for the default int.
A member with no value continues from the one before, starting at zero, so
Real is 10.
The type is its own, which is the other half of the bargain. k + 1 does not
compile, and neither does passing a Kind where an integer is wanted. Crossing
over is written out:
byte := u8(Kind.Text) // 9back := Kind(9) // Kind.TextThe second one is not checked against the members — there is no table at run time to check it against — which is what makes it usable for a value that just came off a socket.
Printing one gives the member’s name, because the number would tell you nothing:
import "std/io"
enum Kind u8 { None Bool Text = 9}
func main() !int { k := Kind.Text try io.Printf("{} is {}, and {}\n", k, u8(k), nameof(Kind.None)) return 0}nameof(k) asks for the name on its own, and gives the empty string for a value
that is not a member.