unwrap()
- If an
Optiontype hasSomevalue or aResulttype has aOkvalue, the value inside them passes to the next step. - If the
Optiontype hasNonevalue or theResulttype hasErrvalue, program panics; IfErr, panics with the error message.
The functionality is bit similar to the following codes, which are using match instead unwrap().
Example with Option and match, before using unwrap()
fn main() {
let x;
match get_an_optional_value() {
Some(v) => x = v, // if Some("abc"), set x to "abc"
None => panic!(), // if None, panic without any message
}
println!("{}", x); // "abc" ; if you change line 14 `false` to `true`
}
fn get_an_optional_value() -> Option<&'static str> {
//if the optional value is not empty
if false {
return Some("abc");
}
//else
None
}
// --------------- Compile-time error ---------------
thread 'main' panicked at 'explicit panic', src/main.rs:5:17
Example with Result and match, before using unwrap()
fn main() {
let x;
match function_with_error() {
Ok(v) => x = v, // if Ok(255), set x to 255
Err(e) => panic!(e), // if Err("some message"), panic with error message "some message"
}
println!("{}", x); // 255 ; if you change line 13 `true` to `false`
}
fn function_with_error() -> Result<u64, String> {
//if error happens
if true {
return Err("some message".to_string());
}
// else, return valid output
Ok(255)
}
// ---------- Compile-time error ----------
thread 'main' panicked at 'some message', src/main.rs:5:19
Same codes in above main functions can be written with unwrap() using two lines.
// 01. unwrap error message for None
fn main() {
let x = get_an_optional_value().unwrap();
println!("{}", x);
}
// --------------- Compile-time error ---------------
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', libcore/option.rs:345:21
// 02. unwrap error message for Err
fn main() {
let x = function_with_error().unwrap();
println!("{}", x);
}
// --------------- Compile-time error ---------------
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: "some message"', libcore/result.rs:945:5
โญ But as you can see, when using unwrap() error messages are not showing the exact line numbers where the panic happens.
expect()
Similar to unwrap() but can set a custom message for the panics.
// 01. expect error message for None
fn main() {
let n: Option<i8> = None;
n.expect("empty value returned");
}
// --------------- Compile-time error ---------------
thread 'main' panicked at 'empty value returned', libcore/option.rs:989:5
// 02. expect error message for Err
fn main() {
let e: Result<i8, &str> = Err("some message");
e.expect("expect error message");
}
// --------------- Compile-time error ---------------
thread 'main' panicked at 'expect error message: "some message"', libcore/result.rs:945:5
unwrap_err() and expect_err() for Result types
The opposite case of unwrap() and expect(); Panics with Ok values, instead Err. Both print the value inside Ok on the error message.
๐ก Usually use with tests.
// 01. unwrap_err error message for Ok
fn main() {
let o: Result<i8, &str> = Ok(8);
o.unwrap_err();
}
// ---------- Compile-time error ----------
thread 'main' panicked at 'called `Result::unwrap_err()` on an `Ok` value: 8', libcore/result.rs:945:5
// 02. expect_err error message for Ok
fn main() {
let o: Result<i8, &str> = Ok(8);
o.expect_err("Should not get Ok value");
}
// ---------- Compile-time error ----------
thread 'main' panicked at 'Should not get Ok value: 8', libcore/result.rs:945:5
unwrap_or(), unwrap_or_default() and unwrap_or_else()
๐ก These are bit similar to
unwrap(), If anOptiontype hasSomevalue or aResulttype has aOkvalue, the value inside them passes to the next step. But when havingNoneorErr, the functionalities are bit different.
unwrap_or()ย : WithNoneorErr, the value you passes tounwrap_or()is passing to the next step. But the data type of the value you passes should match with the data type of the relevantSomeorOk.
fn main() {
let v1 = 8;
let v2 = 16;
let s_v1 = Some(8);
let n = None;
assert_eq!(s_v1.unwrap_or(v2), v1); // Some(v1) unwrap_or v2 = v1
assert_eq!(n.unwrap_or(v2), v2); // None unwrap_or v2 = v2
let o_v1: Result<i8, &str> = Ok(8);
let e: Result<i8, &str> = Err("error");
assert_eq!(o_v1.unwrap_or(v2), v1); // Ok(v1) unwrap_or v2 = v1
assert_eq!(e.unwrap_or(v2), v2); // Err unwrap_or v2 = v2
}
unwrap_or_default()ย : WithNoneorErr, the default value of the data type of the relevantSomeorOk, is passing to the next step.
fn main() {
let v = 8;
let v_default = 0;
let s_v: Option<i8> = Some(8);
let n: Option<i8> = None;
assert_eq!(s_v.unwrap_or_default(), v); // Some(v) unwrap_or_default = v
assert_eq!(n.unwrap_or_default(), v_default); // None unwrap_or_default = default value of v
let o_v: Result<i8, &str> = Ok(8);
let e: Result<i8, &str> = Err("error");
assert_eq!(o_v.unwrap_or_default(), v); // Ok(v) unwrap_or_default = v
assert_eq!(e.unwrap_or_default(), v_default); // Err unwrap_or_default = default value of v
}
unwrap_or_else()ย : Similar tounwrap_or(). The only difference is, instead of passing a value, you have to pass a closure which returns a value with the same data type of the relevantSomeorOk.
fn main() {
let v1 = 8;
let v2 = 16;
let s_v1 = Some(8);
let n = None;
let fn_v2_for_option = || 16;
assert_eq!(s_v1.unwrap_or_else(fn_v2_for_option), v1); // Some(v1) unwrap_or_else fn_v2 = v1
assert_eq!(n.unwrap_or_else(fn_v2_for_option), v2); // None unwrap_or_else fn_v2 = v2
let o_v1: Result<i8, &str> = Ok(8);
let e: Result<i8, &str> = Err("error");
let fn_v2_for_result = |_| 16;
assert_eq!(o_v1.unwrap_or_else(fn_v2_for_result), v1); // Ok(v1) unwrap_or_else fn_v2 = v1
assert_eq!(e.unwrap_or_else(fn_v2_for_result), v2); // Err unwrap_or_else fn_v2 = v2
}