前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Rust 组合器汇总

Rust 组合器汇总

原创
作者头像
谛听
修改2021-12-06 22:12:16
9280
修改2021-12-06 22:12:16
举报
文章被收录于专栏:随意记录

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 错误信息。
  • 源码
代码语言:txt
复制
pub fn expect(self, msg: &str) -> T {
    match self {
        Some(val) => val,
        None => expect_failed(msg),
    }
}
  • 例子
代码语言:txt
复制
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

  • 有值,返回值;否则,中断程序。
  • 源码
代码语言:txt
复制
pub fn unwrap(self) -> T {
    match self {
        Some(val) => val,
        None => panic!("called `Option::unwrap()` on a `None` value"),
    }
}
  • 例子
代码语言:txt
复制
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

  • 有值,返回值;否则返回一个默认值。
  • 源码
代码语言:txt
复制
pub fn unwrap_or(self, def: T) -> T {
    match self {
        Some(x) => x,
        None => def,
    }
}
  • 例子
代码语言:txt
复制
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

  • 有值,返回值;否则,执行闭包。
  • 源码
代码语言:txt
复制
pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
    match self {
        Some(x) => x,
        None => f(),
    }
}
  • 例子
代码语言:txt
复制
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

  • 有值,则执行闭包返回值;否则,返回一个自定义的默认值。
  • 源码
代码语言:txt
复制
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
    match self {
        Some(t) => f(t),
        None => default,
    }
}
  • 例子
代码语言:txt
复制
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

  • 有值,执行闭包;否则执行另一个闭包。
  • 源码
代码语言:txt
复制
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(),
    }
}
  • 例子
代码语言:txt
复制
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。
  • 源码
代码语言:txt
复制
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
    match self {
        Some(x) => Some(f(x)),
        None => None,
    }
}
  • 例子
代码语言:txt
复制
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。
  • 源码
代码语言:txt
复制
pub fn and<U>(self, optb: Option<U>) -> Option<U> {
    match self {
        Some(_) => optb,
        None => None,
    }
}
  • 例子
代码语言:txt
复制
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。
  • 源码
代码语言:txt
复制
pub fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U> {
    match self {
        Some(x) => f(x),
        None => None,
    }
}
  • 例子
代码语言:txt
复制
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。
  • 源码
代码语言:txt
复制
pub fn or(self, optb: Option<T>) -> Option<T> {
    match self {
        Some(_) => self,
        None => optb,
    }
}
  • 例子
代码语言:txt
复制
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

  • 有值,返回自身;否则执行闭包。
  • 源码
代码语言:txt
复制
pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
    match self {
        Some(_) => self,
        None => f(),
    }
}
  • 例子
代码语言:txt
复制
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

  • 取出一个值。
  • 源码
代码语言:txt
复制
pub fn take(&mut self) -> Option<T> {
    mem::replace(self, None)
}
  • 例子
代码语言:txt
复制
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;否则返回自定义的错误。
  • 源码
代码语言:txt
复制
pub fn ok_or<E>(self, err: E) -> Result<T, E> {
    match self {
        Some(v) => Ok(v),
        None => Err(err),
    }
}
  • 例子
代码语言:txt
复制
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;否则执行代表错误的闭包。
  • 源码
代码语言:txt
复制
pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
    match self {
        Some(v) => Ok(v),
        None => Err(err()),
    }
}
  • 例子
代码语言:txt
复制
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 错误信息。
  • 源码
代码语言:txt
复制
pub fn expect(self, msg: &str) -> T {
    match self {
        Ok(t) => t,
        Err(e) => unwrap_failed(msg, &e),
    }
}
  • 例子
代码语言:txt
复制
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

  • 正确,返回值;否则,中断程序。
  • 源码
代码语言:txt
复制
pub fn unwrap(self) -> T {
    match self {
        Ok(t) => t,
        Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e),
    }
}
  • 例子
代码语言:txt
复制
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

  • 正确,返回值;否则,返回默认值。
  • 源码
代码语言:txt
复制
pub fn unwrap_or_default(self) -> T {
    match self {
        Ok(x) => x,
        Err(_) => Default::default(),
    }
}
  • 例子
代码语言:txt
复制
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

  • 正确,返回值;否则返回自定义默认值。
  • 源码
代码语言:txt
复制
pub fn unwrap_or(self, default: T) -> T {
    match self {
        Ok(t) => t,
        Err(_) => default,
    }
}
  • 例子
代码语言:txt
复制
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

  • 正确,返回值;否则,执行闭包。
  • 源码
代码语言:txt
复制
pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T {
    match self {
        Ok(t) => t,
        Err(e) => op(e),
    }
}
  • 例子
代码语言:txt
复制
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

  • 正确,则执行闭包返回值;否则,返回一个自定义的默认值。
  • 源码
代码语言:txt
复制
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
    match self {
        Ok(t) => f(t),
        Err(_) => default,
    }
}
  • 例子
代码语言:txt
复制
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 个闭包。
  • 源码
代码语言:txt
复制
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),
    }
}
  • 例子
代码语言:txt
复制
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。
  • 源码
代码语言:txt
复制
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),
    }
}
  • 例子
代码语言:txt
复制
let ok: Result<&'static str, anyhow::Error> = Ok("value");
assert_eq!(ok.map(|s| s.len()).unwrap(), 5);

3.3.2 map_err

  • 错误,则对错误执行闭包,并返回另一个 Result。
  • 源码
代码语言:txt
复制
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)),
    }
}
  • 例子
代码语言:txt
复制
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。
  • 源码
代码语言:txt
复制
pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> {
    match self {
        Ok(_) => res,
        Err(e) => Err(e),
    }
}
  • 例子
代码语言:txt
复制
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

  • 正确,则执行闭包。
  • 源码
代码语言:txt
复制
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),
    }
}
  • 例子
代码语言:txt
复制
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。
  • 源码
代码语言:txt
复制
pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> {
    match self {
        Ok(v) => Ok(v),
        Err(_) => res,
    }
}
  • 例子
代码语言:txt
复制
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

  • 错误,则执行闭包。
  • 源码
代码语言:txt
复制
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),
    }
}
  • 例子
代码语言:txt
复制
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。
  • 源码
代码语言:txt
复制
pub fn ok(self) -> Option<T> {
    match self {
        Ok(x) => Some(x),
        Err(_) => None,
    }
}
  • 例子
代码语言:txt
复制
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。
  • 源码
代码语言:txt
复制
pub fn err(self) -> Option<E> {
    match self {
        Ok(_) => None,
        Err(x) => Some(x),
    }
}
  • 例子
代码语言:txt
复制
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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 Option 和 Result
  • 2 处理 Option
    • 2.1 None 时发生 panic
      • 2.1.1 expect
      • 2.1.2 unwrap
    • 2.2 返回另外一个值
      • 2.2.1 unwrap_or
      • 2.2.2 unwrap_or_else
      • 2.2.3 map_or
      • 2.2.4 map_or_else
    • 2.3 返回 Option
      • 2.3.1 map
      • 2.3.2 and
      • 2.3.3 and_then
      • 2.3.4 or
      • 2.3.5 or_else
      • 2.3.6 take
    • 2.4 返回 Result
      • 2.4.1 ok_or
      • 2.4.2 ok_or_else
  • 3 处理 Result
    • 3.1 错误时发生 panic
      • 3.1.1 expect
      • 3.1.2 unwrap
    • 3.2 返回另外一个值
      • 3.2.1 unwrap_or_default
      • 3.2.2 unwrap_or
      • 3.2.3 unwrap_or_else
      • 3.2.4 map_or
      • 3.2.5 map_or_else
    • 3.3 返回 Result
      • 3.3.1 map
      • 3.3.2 map_err
      • 3.3.2 and
      • 3.3.3 and_then
      • 3.3.4 or
      • 3.3.5 or_else
    • 3.4 返回 Option
      • 3.4.1 ok
      • 3.4.r err
  • 4 组合 Option 和 Result
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档