Errors, 2 of 4
Error types
Define error Classes with details of their own, catch each kind apart, and wrap one error in another.
What you’ll build
The error handling of a program that loads its settings: a missing setting is one kind of error,
a bad value another, and a missing file a third, from the standard library. Each kind carries the
details its handler needs, and a Catch for each handles it its own way.
A Class of your own
An error type is a Class that extends Error. One without a New of its own takes Error’s, a
message and an optional cause. One that adds fields writes a New, which passes the message on
with Super.New.
Import std.core
Class SettingError Extends Error
End Class
Class MissingSetting Extends SettingError
ReadOnly Field Key: String
New(key: String)
Super.New("'{key}' isn't set")
Key = key
End New
End Class
Function Setting(key: String): String Throws MissingSetting
If key == "host" Then Return "localhost"
Throw MissingSetting(key)
End Function
Try
Print(Setting("host"))
Print(Setting("port"))
Catch e As MissingSetting
Print("missing {e.Key}: {e.Message}")
End Trylocalhost missing port: 'port' isn't set
Catching by Class
Catch e As T catches errors of Class T, or of a Class that extends it; inside it, e is a
T, with its fields. An error goes to the first Catch that matches, so the more specific ones
come first. A Catch that an earlier one covers, or that nothing in the body can throw, is an
error. Catch e with no Class catches the rest.
Import std.core
Class SettingError Extends Error
End Class
Class MissingSetting Extends SettingError
ReadOnly Field Key: String
New(key: String)
Super.New("'{key}' isn't set")
Key = key
End New
End Class
Function Port(settings: String[]): Int Throws SettingError
If settings.Count == 0 Then Throw MissingSetting("port")
Local port = Int.Parse(settings[0])
If port == Null Then Throw SettingError("port '{settings[0]}' isn't a number")
Return port
End Function
For settings In [["8080"], [], ["eighty"]]
Try
Print("port {Port(settings)}")
Catch e As MissingSetting
Print("using the default port, since {e.Key} isn't set")
Catch e As SettingError
Print("can't start: {e.Message}")
End Try
End Forport 8080 using the default port, since port isn't set can't start: port 'eighty' isn't a number
Throws SettingError covers MissingSetting too, since it extends SettingError.
The standard library’s errors
Each area of the standard library has an error type whose Kind, an Enum, says what went wrong.
std.io throws an IOError, with kinds such as NOT_FOUND and PERMISSION_DENIED.
Import std.core
Import std.io
Try
Local text = File.ReadText("settings.ini")
Print(text)
Catch e As IOError
Print(e.Kind)
If e.Kind == IOErrorKind.NOT_FOUND Then Print("no settings file, so using the defaults")
End TryNOT_FOUND no settings file, so using the defaults
An error and its cause
An error can hold the error that led to it, its Cause, so a high-level message keeps the
low-level detail. When an error with a cause goes uncaught, the program prints the whole chain,
each cause on a caused by line.
Import std.core
Import std.io
Function LoadSettings(): String Throws Error
Try
Return File.ReadText("settings.ini")
Catch e As IOError
Throw Error("couldn't load the settings", e)
End Try
End Function
Local settings = Try LoadSettings()
Print(settings)uncaught Error: couldn't load the settings at settings.fb:8:9
caused by IOError: can't read settings.ini: no such file or directory at std/io/request.fb:35:5
at LoadSettings (settings.fb:8)
at top-level code (settings.fb:12)Each error also has a Place: the file, line, and column it was first thrown from, which the
first line of the report shows.
What you learned
- An error type is a Class that extends
Error, with fields for its details. Catch e As Tcatches aTor a Class extending it; put the specific ones first.Throws Basecovers every Class that extendsBase.- std’s errors have a
KindEnum, likeIOError’sNOT_FOUND. Error(message, cause)wraps an error, and an uncaught one prints its causes.
The rules are in the language reference.
Report an issue with this page or with FutureBlitz on GitHub.