1 Option 和 Result
Option<T> 用来表示有无,当有值时,为 Some(T);否则,为 None。
代码语言:txt复制enum Option<T> {
None,
Some(T),
}
Result<T, E> 用来表示是否发生错误,当没有发生错误时,为 Ok(T);否则,为 Err(E)。
代码语言:txt复制enum Result<T, E> {
Ok(T),
Err(E),
}
可以用 match 来匹配 Option 和 Result,也可以用下面提到的组合器简化代码。
2 处理 Option
2.1 None 时发生 panic
2.1.1 expect
- 有值,返回值;否则,中断程序,打印 msg 错误信息。
- 源码
pub fn expect(self, msg: &str) -> T {
match self {
Some(val) => val,
None => expect_failed(msg),
}
}
- 例子
let x = Some("value");
assert_eq!(x.expect("the world is ending"), "value");
let x: Option<&str> = None;
x.expect("the world is ending"); // panics with `the world is ending`
2.1.2 unwrap
- 有值,返回值;否则,中断程序。
- 源码
pub fn unwrap(self) -> T {
match self {
Some(val) => val,
None => panic!("called `Option::unwrap()` on a `None` value"),
}
}
- 例子
let x = Some("air");
assert_eq!(x.unwrap(), "air");
let x: Option<&str> = None;
assert_eq!(x.unwrap(), "air"); // fails
2.2 返回另外一个值
2.2.1 unwrap_or
- 有值,返回值;否则返回一个默认值。
- 源码
pub fn unwrap_or(self, def: T) -> T {
match self {
Some(x) => x,
None => def,
}
}
- 例子
assert_eq!(Some("car").unwrap_or("bike"), "car");
assert_eq!(None.unwrap_or("bike"), "bike");
assert_eq!(None.unwrap_or(2), 2);
2.2.2 unwrap_or_else
- 有值,返回值;否则,执行闭包。
- 源码
pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
match self {
Some(x) => x,
None => f(),
}
}
- 例子
let k = 10;
assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4);
assert_eq!(None.unwrap_or_else(|| 2 * k), 20);
assert_eq!(None.unwrap_or_else(|| "hello"), "hello");
2.2.3 map_or
- 有值,则执行闭包返回值;否则,返回一个自定义的默认值。
- 源码
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
match self {
Some(t) => f(t),
None => default,
}
}
- 例子
let x = Some("foo");
assert_eq!(x.map_or(42, |v| v.len()), 3);
let x: Option<&str> = None;
assert_eq!(x.map_or(42, |v| v.len()), 42);
2.2.4 map_or_else
- 有值,执行闭包;否则执行另一个闭包。
- 源码
pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
match self {
Some(t) => f(t),
None => default(),
}
}
- 例子
let k = 21;
let x = Some("foo");
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3);
let x: Option<&str> = None;
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);
2.3 返回 Option
2.3.1 map
- 改变值,并返回另一个 Option。
- 源码
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
match self {
Some(x) => Some(f(x)),
None => None,
}
}
- 例子
let maybe_some_string = Some(String::from("Hello, World!"));
// `Option::map` takes self *by value*, consuming `maybe_some_string`
let maybe_some_len = maybe_some_string.map(|s| s.len());
assert_eq!(maybe_some_len, Some(13));
2.3.2 and
- 有值,返回另一 Option;否则返回 None。
- 源码
pub fn and<U>(self, optb: Option<U>) -> Option<U> {
match self {
Some(_) => optb,
None => None,
}
}
- 例子
let x = Some(2);
let y: Option<&str> = None;
assert_eq!(x.and(y), None);
let x: Option<u32> = None;
let y = Some("foo");
assert_eq!(x.and(y), None);
let x = Some(2);
let y = Some("foo");
assert_eq!(x.and(y), Some("foo"));
let x: Option<u32> = None;
let y: Option<&str> = None;
assert_eq!(x.and(y), None);
2.3.3 and_then
- 有值,执行闭包;否则返回 None。
- 源码
pub fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U> {
match self {
Some(x) => f(x),
None => None,
}
}
- 例子
fn sq(x: u32) -> Option<u32> { Some(x * x) }
fn nope(_: u32) -> Option<u32> { None }
assert_eq!(Some(2).and_then(sq).and_then(sq), Some(16));
assert_eq!(Some(2).and_then(sq).and_then(nope), None);
assert_eq!(Some(2).and_then(nope).and_then(sq), None);
assert_eq!(None.and_then(sq).and_then(sq), None);
2.3.4 or
- 有值,返回自身;否则返回自定义的 Option。
- 源码
pub fn or(self, optb: Option<T>) -> Option<T> {
match self {
Some(_) => self,
None => optb,
}
}
- 例子
let x = Some(2);
let y = None;
assert_eq!(x.or(y), Some(2));
let x = None;
let y = Some(100);
assert_eq!(x.or(y), Some(100));
let x = Some(2);
let y = Some(100);
assert_eq!(x.or(y), Some(2));
let x: Option<u32> = None;
let y = None;
assert_eq!(x.or(y), None);
2.3.5 or_else
- 有值,返回自身;否则执行闭包。
- 源码
pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
match self {
Some(_) => self,
None => f(),
}
}
- 例子
fn nobody() -> Option<&'static str> { None }
fn vikings() -> Option<&'static str> { Some("vikings") }
assert_eq!(Some("barbarians").or_else(vikings), Some("barbarians"));
assert_eq!(None.or_else(vikings), Some("vikings"));
assert_eq!(None.or_else(nobody), None);
2.3.6 take
- 取出一个值。
- 源码
pub fn take(&mut self) -> Option<T> {
mem::replace(self, None)
}
- 例子
let mut x = Some(2);
let y = x.take();
assert_eq!(x, None);
assert_eq!(y, Some(2));
let mut x: Option<u32> = None;
let y = x.take();
assert_eq!(x, None);
assert_eq!(y, None);
2.4 返回 Result
2.4.1 ok_or
- 有值,返回 Result;否则返回自定义的错误。
- 源码
pub fn ok_or<E>(self, err: E) -> Result<T, E> {
match self {
Some(v) => Ok(v),
None => Err(err),
}
}
- 例子
let x = Some("foo");
assert_eq!(x.ok_or(0), Ok("foo"));
let x: Option<&str> = None;
assert_eq!(x.ok_or(0), Err(0));
2.4.2 ok_or_else
- 有值,返回 Result;否则执行代表错误的闭包。
- 源码
pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
match self {
Some(v) => Ok(v),
None => Err(err()),
}
}
- 例子
let x = Some("foo");
assert_eq!(x.ok_or_else(|| 0), Ok("foo"));
let x: Option<&str> = None;
assert_eq!(x.ok_or_else(|| 0), Err(0));
3 处理 Result
3.1 错误时发生 panic
3.1.1 expect
- 正确,返回值;否则,中断程序,打印 msg 错误信息。
- 源码
pub fn expect(self, msg: &str) -> T {
match self {
Ok(t) => t,
Err(e) => unwrap_failed(msg, &e),
}
}
- 例子
let ok: Result<&'static str, anyhow::Error> = Ok("value");
assert_eq!(ok.expect("the world is ending"), "value");
let err: Result<&'static str, anyhow::Error> = Err(anyhow::anyhow!("error"));
err.expect("the world is ending"); // panics with `the world is ending`
3.1.2 unwrap
- 正确,返回值;否则,中断程序。
- 源码
pub fn unwrap(self) -> T {
match self {
Ok(t) => t,
Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e),
}
}
- 例子
let ok: Result<&'static str, anyhow::Error> = Ok("value");
assert_eq!(ok.unwrap(), "value");
let err: Result<&'static str, anyhow::Error> = Err(anyhow::anyhow!("error"));
err.unwrap(); // fails
3.2 返回另外一个值
3.2.1 unwrap_or_default
- 正确,返回值;否则,返回默认值。
- 源码
pub fn unwrap_or_default(self) -> T {
match self {
Ok(x) => x,
Err(_) => Default::default(),
}
}
- 例子
let good_year_from_input = "1909";
let good_year = good_year_from_input.parse().unwrap_or_default();
assert_eq!(1909, good_year);
let bad_year_from_input = "190blarg";
let bad_year = bad_year_from_input.parse().unwrap_or_default();
assert_eq!(0, bad_year);
3.2.2 unwrap_or
- 正确,返回值;否则返回自定义默认值。
- 源码
pub fn unwrap_or(self, default: T) -> T {
match self {
Ok(t) => t,
Err(_) => default,
}
}
- 例子
let ok: Result<&'static str, anyhow::Error> = Ok("value");
assert_eq!(ok.unwrap_or("other"), "value");
let err: Result<&'static str, anyhow::Error> = Err(anyhow::anyhow!("error"));
assert_eq!(err.unwrap_or("other"), "other");
3.2.3 unwrap_or_else
- 正确,返回值;否则,执行闭包。
- 源码
pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T {
match self {
Ok(t) => t,
Err(e) => op(e),
}
}
- 例子
let ok: Result<&'static str, anyhow::Error> = Ok("value");
assert_eq!(ok.unwrap_or_else(|v| "other"), "value");
let err: Result<&'static str, anyhow::Error> = Err(anyhow::anyhow!("error"));
assert_eq!(err.unwrap_or_else(|v| "other"), "other");
3.2.4 map_or
- 正确,则执行闭包返回值;否则,返回一个自定义的默认值。
- 源码
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
match self {
Ok(t) => f(t),
Err(_) => default,
}
}
- 例子
let ok: Result<&'static str, anyhow::Error> = Ok("value");
assert_eq!(ok.map_or(42, |v| v.len()), 5);
let err: Result<&'static str, anyhow::Error> = Err(anyhow::anyhow!("error"));
assert_eq!(err.map_or(42, |v| v.len()), 42);
3.2.5 map_or_else
- 正确,则执行第 2 个闭包;否则执行第 1 个闭包。
- 源码
pub fn map_or_else<U, D: FnOnce(E) -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
match self {
Ok(t) => f(t),
Err(e) => default(e),
}
}
- 例子
let k = 21;
let ok: Result<&'static str, anyhow::Error> = Ok("value");
assert_eq!(ok.map_or_else(|v| 2 * k, |v| v.len()), 5);
let err: Result<&'static str, anyhow::Error> = Err(anyhow::anyhow!("error"));
assert_eq!(err.map_or_else(|v| 2 * k, |v| v.len()), 42);
3.3 返回 Result
3.3.1 map
- 正确,则改变值,并返回另一个 Result。
- 源码
pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E> {
match self {
Ok(t) => Ok(op(t)),
Err(e) => Err(e),
}
}
- 例子
let ok: Result<&'static str, anyhow::Error> = Ok("value");
assert_eq!(ok.map(|s| s.len()).unwrap(), 5);
3.3.2 map_err
- 错误,则对错误执行闭包,并返回另一个 Result。
- 源码
pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F> {
match self {
Ok(t) => Ok(t),
Err(e) => Err(op(e)),
}
}
- 例子
fn stringify(x: u32) -> String { format!("error code: {}", x) }
let x: Result<u32, u32> = Ok(2);
assert_eq!(x.map_err(stringify), Ok(2));
let x: Result<u32, u32> = Err(13);
assert_eq!(x.map_err(stringify), Err("error code: 13".to_string()));
3.3.2 and
- 正确,则返回另一 Result。
- 源码
pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> {
match self {
Ok(_) => res,
Err(e) => Err(e),
}
}
- 例子
let ok: Result<u32, &str> = Ok(2);
let x1: Result<u32, &str> = Ok(3);
assert_eq!(ok.and(x1), Ok(3));
let err: Result<u32, &str> = Err("error 1");
let x2: Result<u32, &str> = Err("early 2");
assert_eq!(err.and(x2), Err("error 1"));
3.3.3 and_then
- 正确,则执行闭包。
- 源码
pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> {
match self {
Ok(t) => op(t),
Err(e) => Err(e),
}
}
- 例子
fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }
fn err(x: u32) -> Result<u32, u32> { Err(x) }
assert_eq!(Ok(2).and_then(sq).and_then(sq), Ok(16));
assert_eq!(Ok(2).and_then(sq).and_then(err), Err(4));
assert_eq!(Ok(2).and_then(err).and_then(sq), Err(2));
assert_eq!(Err(3).and_then(sq).and_then(sq), Err(3));
3.3.4 or
- 错误,则返回另一个 Result。
- 源码
pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> {
match self {
Ok(v) => Ok(v),
Err(_) => res,
}
}
- 例子
let x: Result<u32, &str> = Ok(2);
let y: Result<u32, &str> = Err("late error");
assert_eq!(x.or(y), Ok(2));
let x: Result<u32, &str> = Err("not a 2");
let y: Result<u32, &str> = Err("late error");
assert_eq!(x.or(y), Err("late error"));
3.3.5 or_else
- 错误,则执行闭包。
- 源码
pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> {
match self {
Ok(t) => Ok(t),
Err(e) => op(e),
}
}
- 例子
fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }
fn err(x: u32) -> Result<u32, u32> { Err(x) }
assert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2));
assert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2));
assert_eq!(Err(3).or_else(sq).or_else(err), Ok(9));
assert_eq!(Err(3).or_else(err).or_else(err), Err(3));
3.4 返回 Option
3.4.1 ok
- 有值,返回值;否则返回 None。
- 源码
pub fn ok(self) -> Option<T> {
match self {
Ok(x) => Some(x),
Err(_) => None,
}
}
- 例子
let ok: Result<u32, anyhow::Error> = Ok(2);
assert_eq!(ok.ok(), Some(2));
let err: Result<u32, anyhow::Error> = Err(anyhow::anyhow!("error"));
assert_eq!(err.ok(), None);
3.4.r err
- 有值,则返回 None。
- 源码
pub fn err(self) -> Option<E> {
match self {
Ok(_) => None,
Err(x) => Some(x),
}
}
- 例子
let x: Result<u32, &str> = Ok(2);
assert_eq!(x.err(), None);
let x: Result<u32, &str> = Err("Nothing here");
assert_eq!(x.err(), Some("Nothing here"));
4 组合 Option 和 Result
以上处理算子可组合使用。
例子:
代码语言:txt复制use std::env;
fn double_arg(mut argv: env::Args) -> Result<i32, String> {
argv.nth(1)
.ok_or("Please give at least one argument".to_owned())
.and_then(|arg| arg.parse::<i32>().map_err(|err| err.to_string()))
.map(|n| 2 * n)
}
fn main() {
match double_arg(env::args()) {
Ok(n) => println!("{}", n),
Err(err) => println!("Error: {}", err),
}
}
2.4.1 节提到,Option 的 ok_or() 返回值为 Result,所以可用 ok_or() 将 Option 转为 Result,进而可继续使用 Result 的处理算子。
也可以用 Result 的 ok() 或 err() 将 Result 转为 Option。
参考
https://www.jianshu.com/p/ce5bddf4b335
https://wiki.jikexueyuan.com/project/rust-primer/error-handling/option-result.html