rust中的map_or()和map_or_else()函数详解

本文介绍了Rust编程中Option和Result类型的map_or及map_or_else函数的使用,详细解析了它们的函数定义和工作原理。通过实例展示了如何在Option和Result中提取值并进行处理。同时,文章还提供了一个实战示例,利用map_or判断列表是否递增。
摘要由CSDN通过智能技术生成

Option<T>Result<T,E>中都定义了map_or/map_or_else函数,函数内部通过match模式匹配,快速提取Option/Result内含的值,并进行进一步的处理。

map_or()函数

先来看看Option<T>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,
    }
}

第一个参数为self,表明map_orOption对象的成员方法(不是通过结构名称可以直接调用的静态方法)。
第二个参数default,是调用者传入的一个默认返回值,跟map_or()的返回值类型相同,都是泛型类型U。
Option对象本身是None时,会将此default作为map_or()的返回值返回出去。
第三个参数f,其类型F是带一个T类型输入参数,返回U类型的FnOnce函数/闭包。其中T类型就是Option<T>中的泛型类型T。
map_or最终返回的是U类型。

关于FnOnce的详细解释,可以参考:Rust 08:函数和闭包(FnOnce、FnMut、Fn)

可以看到,map_or内部封装了一个match匹配,可以在链式调用中,方便地提取Option中的值:

  • 如果本身是Some(t),那么函数调用结果f(t)将会被作为最终的返回值。
  • 如果本身是None,直接返回传给map_or的第一个参数(这里把self当做第0个参数)作为最终的返回值。

接下来,通过定义如下一个is_even()函数来判断一个Option<i32>是不是偶数(None不算偶数)。以此来熟悉map_or的用法:

// 对于一个Option<i32>类型的x,如果x是None,直接返回传给map_or的第一个参数值(false),
// 如果x中有值,则会通过第二个闭包进行处理:i32的值是偶数返回true,是奇数返回false。
fn is_even(x: Option<i32>) -> bool {
    x.map_or(false, |x|x%2==0)
}
println!("{}", is_even(None));//false
println!("{}", is_even(Some(1)));//false
println!("{}", is_even(Some(2)));//true

map_or_else()函数

map_or_elsemap_or不同的是,第一个参数也是FnOnce函数(不同的是,这是一个没有输入的闭包,因为当前只有一个None可用,没必要有输入),在match遇到None时,会调用此函数,而不是直接返回一个默认值。

fn my_unwrap(x: Option<u8>) -> i32 { 
    x.map_or_else(||-1, |x|x as i32)
}
println!("{}", my_unwrap(None));//-1
println!("{}", my_unwrap(Some(1)));//1
println!("{}", my_unwrap(Some(2)));//2

实战:判断递增列表

定义一个函数,判断一个列表中的数是否是递增的(要求用map_or来实现):

fn is_ascending(x: &Vec<i32>) -> bool {
    let mut iter = x.iter();
    // 取出迭代器中第一个元素进行map_or
    iter.next().map_or(true, |mut prev| {
    	// 遍历迭代器中除第一个元素外,其余的元素
        for cur in iter {
            if cur >= prev {
                prev = cur;
            } else {
                return false;
            }
        }
        true
    })
}
println!("{}", is_ascending(&vec![]));//true
println!("{}", is_ascending(&vec![1,2,5]));//true
println!("{}", is_ascending(&vec![9,2,5]));//false

补充

Result<T,E>中的map_or/map_or_else也是同样的用法。不同之处,仅仅在于Option<T>中用于匹配None的情况,在Result<T,E>中被换成了Err(e)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值