do, try, catch
Part of the Logic & Flow section of Coddy's Swift journey — lesson 45 of 56.
The full form for handling errors is do/try/catch:
enum DivError: Error { case byZero }
func divide(_ a: Int, _ b: Int) throws -> Int {
if b == 0 { throw DivError.byZero }
return a / b
}
do {
let r = try divide(10, 2)
print(r) // 5
} catch DivError.byZero {
print("can't divide by zero")
} catch {
print("unknown error")
}try goes in front of any throwing call. If the call throws, control jumps to the matching catch; otherwise execution falls through past the do block.
Multiple catch clauses run top-to-bottom and the first match wins, just like a switch. The bare catch at the end is the catch-all, you almost always want one to keep the compiler happy.
Challenge
EasyDefine an enum ParseError: Error with three cases: empty, notInteger, and negative.
Define a throwing function parsePositive(_ s: String) throws -> Int that:
- Throws
.emptywhenstrimmed of whitespace is empty - Throws
.notIntegerwhenscan't be parsed asInt - Throws
.negativewhen the parsed value is< 0 - Otherwise returns the parsed value
Read a single line from stdin and call parsePositive in a do/catch block. Print:
got: <n>on successerror: empty,error: not integer, orerror: negativefor each case
For input 42, the output is got: 42. For an empty line, it's error: empty. For abc it's error: not integer.
Cheat sheet
Swift error handling uses do/try/catch. Define errors with an enum conforming to Error, mark throwing functions with throws, and use throw to raise an error:
enum DivError: Error { case byZero }
func divide(_ a: Int, _ b: Int) throws -> Int {
if b == 0 { throw DivError.byZero }
return a / b
}
do {
let r = try divide(10, 2)
print(r) // 5
} catch DivError.byZero {
print("can't divide by zero")
} catch {
print("unknown error") // catch-all
}trymust precede every throwing call.catchclauses are matched top-to-bottom; first match wins.- A bare
catchat the end acts as a catch-all.
Try it yourself
let line = readLine()!
// TODO: enum ParseError; func parsePositive(_:) throws -> Int;
// do/try/catch with three branches plus the catch-all
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Logic & Flow
1Strings In Depth
Count and IndicesCase and TrimSearching in StringsSplitting and JoiningReplacing SubstringsRecap - Username Check