【Rust自学】13.2. 闭包 Pt.2:闭包的类型推断和标注

发布时间:2026/7/23 18:57:10
【Rust自学】13.2. 闭包 Pt.2:闭包的类型推断和标注 13.2 闭包 Pt.2闭包的类型推断和标注13.2.0. 写在正文之前Rust语言在设计过程中受到了很多语言的启发而函数式编程对Rust产生了非常显著的影响。函数式编程通常包括通过将函数作为值传递给参数、从其他函数返回它们、将它们分配给变量以供以后执行等等。在本章中我们会讨论 Rust 的一些特性这些特性与许多语言中通常称为函数式的特性相似-闭包本文- 迭代器- 使用闭包和迭代器改进I/O项目- 闭包和迭代器的性能13.2.1. 闭包的类型推断和fn定义的函数不同闭包不强制要求标注参数和返回值的类型。函数需要强制标注是因为它是暴露给用户的显示接口的一部分严格定义接口有助于所有人对参数和返回值的类型取得共识。闭包并不会被用于这样的暴露接口只会被存于变量中使用时也不需要命名更不会被暴露给我们代码库的用户。所以闭包不强制要求标注参数和返回值的类型。而且闭包通常很短小只在狭小的上下文中工作编译器通常能推断出类型。当然你手动标注出来也不是不可以。看个例子这是使用函数定义的代码fn simulated_expensive_calculation(intensity: u32) - u32 { println!(calculating slowly...); thread::sleep(Duration::from_secs(2)); intensity }这是使用闭包的代码let expensive_closure |num:u32| - u32 { println!(calculating slowly...); thread::sleep(Duration::from_secs(2)); num };这里使用显式标注是因为没有前后文供Rust推断类型如果有就不需要fn generate_workout(intensity: u32, random_number: u32) { let expensive_closure |num| { println!(calculating slowly...); thread::sleep(Duration::from_secs(2)); num }; if intensity 25 { println!(Today, do {} pushups!, expensive_closure(intensity)); println!(Next, do {} situps!, expensive_closure(intensity)); } else { if random_number 3 { println!(Take a break today! Remember to stay hydrated!); } else { println!(Today, run for {} minutes!, expensive_closure(intensity)); } } }这里的参数num不需要显式声明类型是因为下文的调用中传进去的参数intensity的类型为u32Rust推断出num的类型为u32。13.2.2. 函数和闭包定义的语法这里有4个例子fn add_one_v1 (x: u32) - u32 { x 1 } let add_one_v2 |x: u32| - u32 { x 1 }; let add_one_v3 |x| { x 1 }; let add_one_v4 |x| x 1 ;第一个是函数的定义有函数名形参名及类型和返回值类型第二个是闭包的定义有参数和返回值的类型。这个闭包看着和函数的定义差不多。第三个同样是闭包但是没有标注参数和返回值的类型就得靠编译器推断了。第四个闭包跟第三个的不同之处在于没有了花括号{}。因为只有一个表达式所以闭包的{}也可以被省略13.2.3. 闭包的类型推断闭包的定义最终只会为参数/返回值推断出唯一具体的类型。看个例子let example_closure |x| x; let s example_closure(String::from(hello)); let n example_closure(5);输出$ cargo run Compiling closure-example v0.1.0 (file:///projects/closure-example) error[E0308]: mismatched types -- src/main.rs:5:29 | 5 | let n example_closure(5); | --------------- ^ expected String, found integer | | | arguments to this function are incorrect | note: expected because the closure was earlier called with an argument of type String -- src/main.rs:4:29 | 4 | let s example_closure(String::from(hello)); | --------------- ^^^^^^^^^^^^^^^^^^^^^ expected because this argument is of type String | | | in this closure call note: closure parameter defined here -- src/main.rs:2:28 | 2 | let example_closure |x| x; | ^ help: try using a conversion method | 5 | let n example_closure(5.to_string()); | For more information about this error, try rustc --explain E0308. error: could not compile closure-example (bin closure-example) due to 1 previous errorRust编译器在闭包第一次被调用时发现它接收的值和输出的值都是String类型就锁定这个闭包的参数和返回值都是String类型。所以后面又使用i32类型时就会报错。