Skip to content

闭包应用

> 掌握闭包作为函数参数的用法,学会与迭代器配合处理数据。

闭包作为函数参数

基本用法

rust
// 接受闭包作为参数
fn apply<F>(f: F)
where
    F: FnOnce(i32) -> i32,
{
    let result = f(42);
    println!("结果:{}", result);
}

fn main() {
    // 传递闭包
    apply(|x| x + 1);
    apply(|x| x * 2);

    // 也可以传递函数
    fn add_one(x: i32) -> i32 { x + 1 }
    apply(add_one);
}
▶ Run

实际应用:数据处理

rust
// 通用的数据处理函数
fn process_data<F>(data: Vec<i32>, transform: F) -> Vec<i32>
where
    F: Fn(i32) -> i32,
{
    data.into_iter().map(transform).collect()
}

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

    // 不同的转换逻辑
    let doubled = process_data(data.clone(), |x| x * 2);
    let squared = process_data(data.clone(), |x| x * x);
    let offset = process_data(data.clone(), |x| x + 10);

    println!("原始:{:?}", data);
    println!("翻倍:{:?}", doubled);
    println!("平方:{:?}", squared);
    println!("偏移:{:?}", offset);
}
▶ Run

回调模式

rust
// 带有回调的异步操作模拟
fn fetch_with_callback<F>(url: &str, callback: F)
where
    F: FnOnce(Result<String, String>),
{
    // 模拟网络请求
    let result = if url.is_empty() {
        Err("URL 不能为空".to_string())
    } else {
        Ok(format!("从 {} 获取的数据", url))
    };

    // 调用回调
    callback(result);
}

fn main() {
    fetch_with_callback("https://example.com", |result| {
        match result {
            Ok(data) => println!("成功:{}", data),
            Err(e) => println!("错误:{}", e),
        }
    });

    fetch_with_callback("", |result| {
        if let Err(e) = result {
            println!("处理错误:{}", e);
        }
    });
}
▶ Run

迭代器与闭包

常用迭代器方法

rust
fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // map - 转换每个元素
    let doubled: Vec<i32> = numbers
        .iter()
        .map(|x| x * 2)
        .collect();
    println!("翻倍:{:?}", doubled);

    // filter - 过滤元素
    let evens: Vec<&i32> = numbers
        .iter()
        .filter(|x| *x % 2 == 0)
        .collect();
    println!("偶数:{:?}", evens);

    // filter_map - 过滤并转换
    let squared_evens: Vec<i32> = numbers
        .iter()
        .filter_map(|x| {
            if *x % 2 == 0 {
                Some(x * x)
            } else {
                None
            }
        })
        .collect();
    println!("偶数的平方:{:?}", squared_evens);
}
▶ Run

累积操作

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

    // fold - 累积求和
    let sum: i32 = numbers
        .iter()
        .fold(0, |acc, x| acc + x);
    println!("总和:{}", sum);  // 15

    // fold - 累积乘积
    let product: i32 = numbers
        .iter()
        .fold(1, |acc, x| acc * x);
    println!("乘积:{}", product);  // 120

    // scan - 带状态的迭代
    let mut accumulated = 0;
    let running_sum: Vec<i32> = numbers
        .iter()
        .scan(0, |state, &x| {
            *state += x;
            Some(*state)
        })
        .collect();
    println!("累加和:{:?}", running_sum);  // [1, 3, 6, 10, 15]
}
▶ Run

查找与检查

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

    // find - 查找第一个匹配的元素
    let found = numbers.iter().find(|x| *x > 3);
    println!("找到:{:?}", found);  // Some(4)

    // position - 查找索引
    let pos = numbers.iter().position(|x| *x == 3);
    println!("位置:{:?}", pos);  // Some(2)

    // rfind - 从右向左查找
    let rfound = numbers.iter().rfind(|x| *x > 2);
    println!("从右查找:{:?}", rfound);  // Some(5)

    // all - 检查是否全部满足
    let all_positive = numbers.iter().all(|x| *x > 0);
    println!("全部正数:{}", all_positive);  // true

    // any - 检查是否有任意满足
    let has_even = numbers.iter().any(|x| *x % 2 == 0);
    println!("有偶数:{}", has_even);  // true

    // count - 计数
    let even_count = numbers.iter().filter(|x| *x % 2 == 0).count();
    println!("偶数个数:{}", even_count);  // 2
}
▶ Run

排序与闭包

rust
fn main() {
    // 数字排序
    let mut numbers = vec![5, 2, 8, 1, 9];
    numbers.sort();
    println!("升序:{:?}", numbers);

    // 自定义排序:降序
    let mut numbers = vec![5, 2, 8, 1, 9];
    numbers.sort_by(|a, b| b.cmp(a));
    println!("降序:{:?}", numbers);

    // 按绝对值排序
    let mut numbers = vec![-5, 2, -8, 1, 9];
    numbers.sort_by_key(|x| x.abs());
    println!("按绝对值:{:?}", numbers);

    // 字符串按长度排序
    let mut words = vec!["rust", "a", "programming", "is", "language"];
    words.sort_by_key(|s| s.len());
    println!("按长度:{:?}", words);

    // 复杂排序:先按长度,再按字典序
    let mut words = vec!["rust", "a", "programming", "is", "language"];
    words.sort_by(|a, b| {
        a.len().cmp(&b.len()).then(a.cmp(b))
    });
    println!("复杂排序:{:?}", words);
}




---

## 小结

- 闭包作为函数参数,实现回调模式和高阶函数
- 迭代器方法 map、filter、fold 都接受闭包
- 链式调用实现简洁的数据处理管道
- 排序方法 sort_by、sort_by_key 使用闭包定制比较
- find、position、all、any 是常用的查询方法

## 练习题

详见:[练习题](../../exercises/18-closures)
▶ Run