Your own types, 5 of 8
Enums
Name a fixed set of values, handle each in a Select that the compiler checks, and combine flags.
What you’ll build
A blog’s article workflow: each article has a status, from draft to archived, and each editor has a set of permissions. An Enum names each possible value, so the program can’t hold a status that doesn’t exist.
Declaring an Enum
An Enum lists its members, separated by commas or on lines of their own. Each member is used
through the Enum’s name, like Status.Review, and prints as its name. Behind each member is an
integer, from 0 up, unless a member is given its own value.
Import std.core
Enum Status
Draft
Review
Published = 10
Archived
End Enum
Local status = Status.Review
Print(status, status == Status.Review)
Print(Status.Draft As Int, Status.Archived As Int)
Print(10 As Status)Review True 0 11 Published
Archived follows Published, so it’s 11. As turns a member into its integer and back. An
integer that isn’t one of the Enum’s values is an error when the compiler can see it, as in
3 As Status, and a panic when the program runs.
Select over every member
A Select on an Enum must handle every member, or have a Default. Leaving a member out is an
error that names it, so adding a member later points at each Select that has to handle it.
Since this Select covers every member, the function returns a value on every path.
Import std.core
Enum Status
Draft, Review, Published, Archived
End Enum
Function Label(status: Status): String
Select status
Case Status.Draft
Return "being written"
Case Status.Review
Return "waiting for an editor"
Case Status.Published
Return "live"
Case Status.Archived
Return "taken down"
End Select
End Function
Local statuses = [Status.Draft, Status.Published, Status.Archived]
For status In statuses
Print("{status:<10} {Label(status)}")
End ForDraft being written Published live Archived taken down
Without the Case for Status.Archived, the program doesn’t build. fb names the member left
out, and says too that Label then has a path that returns nothing:
Import std.core
Enum Status
Draft, Review, Published, Archived
End Enum
Function Label(status: Status): String
Select status
Case Status.Draft
Return "being written"
Case Status.Review
Return "waiting for an editor"
Case Status.Published
Return "live"
End Select
End Function
Print(Label(Status.Draft))Compiling articles.fb articles.fb:7:10: error: 'Label' doesn't return a value on every path | 7 | Function Label(status: Status): String | ^^^^^ articles.fb:8:12: error: Select doesn't cover Status.Archived; add a Case for each, or a Default | 8 | Select status | ^^^^^^ error: couldn't build articles.fb because of 2 errors
Flags
A @Flags Enum’s members are bits, 1, 2, 4, and so on, so a value can hold several at once.
| combines them, and Has asks whether a value has all the flags given. A combination prints
as its members’ names. Since a @Flags value can be any combination, a Select on one always
needs a Default.
Import std.core
@Flags Enum Access
Read, Write, Publish, Delete
End Enum
Local author = Access.Read | Access.Write
Local editor = author | Access.Publish
Print(author, editor)
Print(author.Has(Access.Write), author.Has(Access.Publish))
Print(editor.Has(Access.Read | Access.Publish))
Print(editor & ~Access.Write)Read | Write Read | Write | Publish True False True Read | Publish
~ flips every bit, so ~Access.Write is every flag but Write, and editor & ~Access.Write
keeps the editor’s flags without Write.
An Enum in a type
An Enum is a value like a number, so it fits in a field. A field of one starts at the Enum’s zero: its first member, or no flags at all for a @Flags Enum.
Import std.core
Enum Status
Draft, Review, Published
End Enum
Class Article
ReadOnly Field Title: String
Field status: Status
New(title: String)
Title = title
End New
Method Advance()
Select status
Case Status.Draft
status = Status.Review
Case Status.Review
status = Status.Published
Case Status.Published
Print("{Title} is already published")
End Select
End Method
End Class
Local article = Article("Hello")
For step = 1 To 3
article.Advance()
Print(article.status)
End ForReview Published Hello is already published Published
What you learned
- An
Enumnames a fixed set of values, each an integer underneath. - Members print as their names, and
Asconverts to and from integers. - A
Selecton an Enum must cover every member or have aDefault; on a @Flags Enum, it always has aDefault. @Flagsmembers are bits that combine with|, andHastests them.- An Enum’s zero is its first member, or no flags for a @Flags Enum.
The rules are in the language reference.
Report an issue with this page or with FutureBlitz on GitHub.