灿飞屋头像
Rust原来很简单四:释放 Rust 的真正威力封面图

Rust原来很简单四:释放 Rust 的真正威力

Part 4 · 进阶篇 —— 释放 Rust 的真正威力

本篇覆盖 第 17 ~ 23 章:闭包与迭代器、智能指针、并发、异步、unsafe 与 FFI、宏系统、Cargo 深入。这是从“会写 Rust”到“精通 Rust”的分水岭。


第 17 章 闭包与迭代器

17.1 闭包(Closure):能捕获环境的匿名函数

fn main() {
   
   
    let factor = 3;
    // 闭包:|参数| 表达式,能捕获外部变量 factor
    let multiply = |x: i32| x * factor;
    println!("{}", multiply(5));    // 15

    // 类型可推断,也可显式标注
    let add = |a: i32, b: i32| -> i32 {
   
    a + b };
    println!("{}", add(2, 3));      // 5

    // 多行闭包用花括号
    let describe = |x: i32| {
   
   
        let doubled = x * 2;
        format!("{x} 的两倍是 {doubled}")
    };
    println!("{}", describe(4));
}

17.2 闭包如何捕获环境:三种方式

闭包会根据你对捕获变量的使用方式,自动选择捕获策略,对应三个 trait:

Trait 捕获方式 触发条件 类比
Fn 不可变借用 &T 只读捕获的变量 借来看
FnMut 可变借用 &mut T 修改捕获的变量 借来改
FnOnce 获取所有权 T 消耗捕获的变量(如 move 走) 借走不还

每个闭包同时实现它所需的最小 trait:FnOnce ⊃ FnMut ⊃ Fn(Fn 一定也是 FnMut 和 FnOnce)。

fn main() {
   
   
    let list = vec![1, 2, 3];

    // Fn:只读借用
    let only_read = || println!("{:?}", list);
    only_read();
    println!("{:?}", list);   // list 仍可用

    // FnMut:可变借用
    let mut count = 0;
    let mut increment = || {
   
    count += 1; };
    increment();
    increment();
    println!("count = {count}");   // 2

    // FnOnce:消耗所有权
    let owned = String::from("bye");
    let consume = move || println!("{owned}");   // move 强制夺取所有权
    consume();
    // consume();   // ❌ 若闭包是 FnOnce,只能调用一次
}

move 关键字:强制闭包获取捕获变量的所有权(而非借用)。在把闭包传到别的线程、或让它活得比当前作用域久时必需(第 19 章并发大量使用)。

17.3 闭包作为参数与返回值

// 接收闭包作参数
fn apply<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
   
   
    f(x)
}

// 返回闭包:必须用 impl Fn 或 Box<dyn Fn>(因为闭包类型匿名)
fn make_adder(x: i32) -> impl Fn(i32) -> i32 {
   
   
    move |y| x + y        // move 捕获 x
}

fn main() {
   
   
    println!("{}", apply(|n| n * 2, 10));   // 20
    let add5 = make_adder(5);
    println!("{}", add5(3));                 // 8
}

17.4 迭代器(Iterator):Rust 的函数式核心

迭代器是 Rust 处理集合的惯用方式,惰性求值、零成本、链式优雅。

fn main() {
   
   
    let v = vec![1, 2, 3, 4, 5];

    // 创建迭代器的三种方式
    let _borrow = v.iter();          // 迭代 &T(不可变借用)
    let _mut = v.iter_mut();         // 迭代 &mut T(可变借用)
    let _owned = v.into_iter();      // 迭代 T(获取所有权,消耗 v)

    // 惰性:不消费就不执行
    let iter = v.iter().map(|x| x * 2);   // 此时还没计算

    // 消费适配器(触发计算,返回单一值)
    let sum: i32 = v.iter().sum();
    let collected: Vec<i32> = v.iter().map(|x| x * 2).collect();
    let count = v.iter().count();

    println!("sum={sum}, count={count}, doubled={collected:?}");
}

17.5 迭代器适配器大全(必背)

let nums = vec![1, 2, 3, 4, 5, 6];

// map:转换每个元素
let doubled: Vec<i32> = nums.iter().map(|x| x * 2).collect();

// filter:过滤
let evens: Vec<&i32> = nums.iter().filter(|x| *x % 2 == 0).collect();

// filter_map:过滤 + 转换(处理 Option)
let words = vec!["1", "two", "3"];
let parsed: Vec<i32> = words.iter()
    .filter_map(|s| s.parse::<i32>().ok())
    .collect();                       // [1, 3]

// fold:累积(reduce 的通用版)
let product = nums.iter().fold(1, |acc, x| acc * x);   // 720

// reduce:fold 的简化(用第一个元素作初值)
let sum = nums.iter().copied().reduce(|a, b| a + b);   // Some(21)

// enumerate:带索引
for (i, x) in nums.iter().enumerate() {
   
   
    print!("{i}:{x} ");
}

// zip:并行迭代两个集合
let a = vec![1, 2, 3];
let b = vec!["one", "two", "three"];
let pairs: Vec<_> = a.iter().zip(b.iter()).collect();

// take / skip
let first3: Vec<&i32> = nums.iter().take(3).collect();
let after2: Vec<&i32> = nums.iter().skip(2).collect();

// chain:串联
let all: Vec

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/canfeit/article/details/170147808

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--