Rust:功能强大的组合器

Rust 能够用组合器简化代码编写。之前觉得没啥用,实际完成一个项目后,才知道组合器的威力强大。下面列举一下常见的组合器,可用于 Option、Result、集合等类型。

一、数值转换:数据类型不变,仅数值替换

1. or()

例子:

fn main() {
    let x=Some(1);
    let y = Some(2);
    let z1 = x.or(y);
    let z2 = None.or(y);
    println!("{:?}", z1);
    println!("{:?}", z2);
}
======== cargo run ========
Some(1)
Some(2)

组合器实现代码:

    pub fn or(self, optb: Option<T>) -> Option<T> {
        match self {
            Some(_) => self,
            None => optb,
        }
    }

2. and()

例子:

fn main() {
    let x = Some(1);
    let y = Some(2);
    let z = x.and(y);
    println!("{:?}", z);
}
======== cargo run ========
Some(2)

组合器实现代码:

    pub fn and<U>(self, optb: Option<U>) -> Option<U> {
        match self {
            Some(_) => optb,
            None => None,
        }
    }

3. or_else()

例子:

fn main() {
    let x = Some(1);
    let z = x.or_else(||Some(2));
    println!("{:?}", z);
}
======== cargo run ========
Some(1)

组合器实现代码:

    pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
        match self {
            Some(_) => self,
            None => f(),
        }
    }

FnOnce 说明这个函数的参数是个闭包。

4. and_then()

例子:

fn main() {
    let x = Some(1);
    let z = x.and_then(|x| Some(x + 1));
    println!("{:?}", z);
}
======== cargo run ========
Some(2)

组合器实现代码:

    pub fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U> {
        match self {
            Some(x) => f(x),
            None => None,
        }
    }

FnOnce(T) 说明这个函数的参数是个闭包,而且以 T 为闭包函数的传入参数。

5. filter

例子:

fn main() {
    let x = Some(3);
    let x1 = x.filter(|x| x < &5);
    let x2 = x.filter(|x| x > &5);
    println!("x1 = {:?}", x1);
    println!("x2 = {:?}", x2);
}
======== cargo run ========
x1 = Some(3)
x2 = None

组合器实现代码:

   pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
        if let Some(x) = self {
            if predicate(&x) {
                return Some(x);
            }
        }
        None
   }

话说 filter 也可用于数组,写了段代码如下:

fn main() {
    let x = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let z = x.iter().filter(|x| **x < 5).collect::<Vec<_>>();
    println!("z= {:?}", z);
}
======== cargo run ========
z= [1, 2, 3, 4]

组合器实现代码:

    fn filter<P>(self, predicate: P) -> Filter<Self, P>
    where
        Self: Sized,
        P: FnMut(&Self::Item) -> bool,
    {
        Filter::new(self, predicate)
    }

看代码,此 filter 非彼 filter。

二、类型转换:用新类型的数据替换原来的数据

1. map()

例子:

fn main() {
    let x = Some("12345");
    let z = x.map(|x| x.len());
    println!("z = {:?}", z);
}
======== cargo run ========
z = Some(5)

组合器实现代码:

    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
        match self {
            Some(x) => Some(f(x)),
            None => None,
        }
    }

用于集合的例子。和上面的不是同一个map,后面所有的组合器实现代码都不贴了:

fn main() {
    let x = vec![1, 2, 3, 4, 5];
    let z = x.iter().map(|x| (*x) as f64).collect::<Vec<f64>>();
    println!("z = {:?}", z);
}
======== cargo run ========
z = [1.0, 2.0, 3.0, 4.0, 5.0]

2. map_err()

只修改 Err 的值, Ok的值不变。看例子:

fn main() {
    let x: Result<i32, i32> = Ok(123);
    let y: Result<i32, i32> = Err(456);
    let z1: Result<i32, i32> = x.map_err(|_| 999);
    let z2: Result<i32, i32> = y.map_err(|_| 999);
    println!("z1 = {:?}", z1);
    println!("z2 = {:?}", z2);
}
======== cargo run ========
z1 = Ok(123)
z2 = Err(999)

3. map_or()

仅支持 Option 类型(不支持 Result )。将闭包应用于 Some 中的值,然后根据闭包返回输出。对于 None 将返回给定的默认值。

fn main() {
    let x: Option<i32> = Some(123);
    let y: Option<i32> = None;
    let z1 = x.map_or(999, |x| x * 2);
    let z2 = y.map_or(999, |x| x * 2);
    println!("z1 = {:?}", z1);
    println!("z2 = {:?}", z2);
}
======== cargo run ========
z1 = 246
z2 = 999

4. map_or_else()

支持 Option 类型和 Results 类型(Result 还在 nightly)。与 map_or() 类似,但要对于第一个参数,要提供另一个闭包,而不是默认值。

fn main() {
    let x: Option<i32> = Some(123);
    let y: Option<i32> = None;
    let z1 = x.map_or_else(|| 999, |x| x * 2);
    let z2 = y.map_or_else(|| 999, |x| x * 2);
    println!("z1 = {:?}", z1);
    println!("z2 = {:?}", z2);
}
======== cargo run ========
z1 = 246
z2 = 999

5. ok_or() : Option -> Result

ok_or() 将Option类型转换为Result类型。
例子:

fn main() {
    let x = Some(123);
    let y: Option<i32> = None;
    let z1: Result<i32, i32> = x.ok_or(999);
    let z2: Result<i32, i32> = y.ok_or(999);
    println!("z1 = {:?}", z1);
    println!("z2 = {:?}", z2);
}
======== cargo run ========
z1 = Ok(123)
z2 = Err(999)

6. ok_or_else() : Option -> Result

ok_or_else() 将Option类型转换为Result类型,用闭包作为参数。

fn main() {
    let x = Some(123);
    let y: Option<i32> = None;
    let z1: Result<i32, i32> = x.ok_or_else(||999);
    let z2: Result<i32, i32> = y.ok_or_else(||999);
    println!("z1 = {:?}", z1);
    println!("z2 = {:?}", z2);
}
======== cargo run ========
z1 = Ok(123)
z2 = Err(999)

三、变量形态变化

1. as_ref():Some(T) -> Some(&T), Result<S,T> -> Result<&S,&T>

例子(Option):

fn print_type_of<T>(_: &T) {
    println!("{}", std::any::type_name::<T>())
}
fn main() {
    let mut x= Some(123);
    print_type_of(&x);
    let z = x.as_ref();
    print_type_of(&z);
}
======== cargo run ========
core::option::Option<i32>
core::option::Option<&i32>

例子(Result):

fn print_type_of<T>(_: &T) {
    println!("{}", std::any::type_name::<T>())
}
fn main() {
    let mut x:Result<i32,i32>= Ok(123);
    print_type_of(&x);
    let z = x.as_ref();
    print_type_of(&z);
}
======== cargo run ========
core::result::Result<i32, i32>
core::result::Result<&i32, &i32>

2. as_mut():Option(T) -> Option(&mut T), Result<S,T> -> Result<&mut S,&mut T>

例子(Option):

fn print_type_of<T>(_: &T) {
    println!("{}", std::any::type_name::<T>())
}
fn main() {
    let mut x= Some(123);
    print_type_of(&x);
    let z = x.as_mut();
    print_type_of(&z);
}
======== cargo run ========
core::option::Option<i32>
core::option::Option<&mut i32>

例子(Result):

fn print_type_of<T>(_: &T) {
    println!("{}", std::any::type_name::<T>())
}
fn main() {
    let mut x:Result<i32,i32>= Ok(123);
    print_type_of(&x);
    let z = x.as_mut();
    print_type_of(&z);
}
======== cargo run ========
core::result::Result<i32, i32>
core::result::Result<&mut i32, &mut i32>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许野平

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值