Error Handling Patterns
Option to Result
Adding an Error Message
Option says a value may be absent. ok_or turns absence into a Result with an explicit error value.
Program
Play the program to look up a selected setting and label missing keys.
option_to_result.rs
Replay: real traced execution (multi-file project)
fn lookup(key: &str) -> Result<&'static str, &'static str> {
let value = match key {
"host" => Some("local"),
"port" => Some("8080"),
_ => None,
};
value.ok_or("missing")
}
fn main() {
let key = "host";
let result = lookup(key);
let label = match result {
Ok(value) => format!("{key}={value}"),
Err(error) => format!("{key}:{error}"),
};
println!("{label}");
}
fn lookup(key: &str) -> Result<&'static str, &'static str> {
let value = match key {
"host" => Some("local"),
"port" => Some("8080"),
_ => None,
};
value.ok_or("missing")
}
fn main() {
let key = "port";
let result = lookup(key);
let label = match result {
Ok(value) => format!("{key}={value}"),
Err(error) => format!("{key}:{error}"),
};
println!("{label}");
}
fn lookup(key: &str) -> Result<&'static str, &'static str> {
let value = match key {
"host" => Some("local"),
"port" => Some("8080"),
_ => None,
};
value.ok_or("missing")
}
fn main() {
let key = "debug";
let result = lookup(key);
let label = match result {
Ok(value) => format!("{key}={value}"),
Err(error) => format!("{key}:{error}"),
};
println!("{label}");
}
key ← "host"
10fn main() {11 let ke→ "host"y = "host"; //@key="host", "port", "debug"12 let result = lookup(ke"host"y);13 let label = match result {value ← Some("local")
1fn lookup(key: &str) -> Result<&'static str, &'static str> {2 let valu→ Some("local")e = match ke"host"y {3 "host" => Some("local"),4 "port" => Some("8080"),5 _ => None,6 };7 value.ok_or("missing")8}result ← Ok("local"), label ← "host=local"
11 let key = "host"; //@key="host", "port", "debug"12 let resul→ Ok("local")t = lookup(ke"host"y);13 let labe→ "host=local"l = match resulOk("local")t {14 Ok(value) => format!("{key}={value}"),15 Err(error) => format!("{key}:{error}"),16 };17 println!("{label}");18}outputhost=local
key ← "port"
10fn main() {11 let ke→ "port"y = "port";12 let result = lookup(ke"port"y);13 let label = match result {value ← Some("8080")
1fn lookup(key: &str) -> Result<&'static str, &'static str> {2 let valu→ Some("8080")e = match ke"port"y {3 "host" => Some("local"),4 "port" => Some("8080"),5 _ => None,6 };7 value.ok_or("missing")8}result ← Ok("8080"), label ← "port=8080"
11 let key = "port";12 let resul→ Ok("8080")t = lookup(ke"port"y);13 let labe→ "port=8080"l = match resulOk("8080")t {14 Ok(value) => format!("{key}={value}"),15 Err(error) => format!("{key}:{error}"),16 };17 println!("{label}");18}outputport=8080
key ← "debug"
10fn main() {11 let ke→ "debug"y = "debug";12 let result = lookup(ke"debug"y);13 let label = match result {value ← None
1fn lookup(key: &str) -> Result<&'static str, &'static str> {2 let valu→ Nonee = match ke"debug"y {3 "host" => Some("local"),4 "port" => Some("8080"),5 _ => None,6 };7 value.ok_or("missing")8}result ← Err("missing"), label ← "debug:missing"
11 let key = "debug";12 let resul→ Err("missing")t = lookup(ke"debug"y);13 let labe→ "debug:missing"l = match resulErr("missing")t {14 Ok(value) => format!("{key}={value}"),15 Err(error) => format!("{key}:{error}"),16 };17 println!("{label}");18}outputdebug:missing
Follow the Conversion
- A lookup starts as an
Option. Some(value)means the key was present.Nonemeans the key was missing.ok_orturns the missing case into anErr. | Beforeok_or| Afterok_or| | --- | --- | |Some(value)|Ok(value)| |None|Err(message)|
Option
`Option<T>` is either `Some(T)` or `None`.
ok_or
`ok_or(error)` turns `Some` into `Ok` and `None` into `Err(error)`.
lookup result
The caller gets a `Result` with a clear missing-key label.
Exercise: option_to_result.rs
Look up a required setting with ok_or and return a Result that names the missing key