Rust从入门到实战系列三百四十一:闭包类型推断和注解

闭包不要求像 fn 函数那样在参数和返回值上注明类型。函数中需要类型注解是因为他们是暴露给用户的
显式接口的一部分。严格的定义这些接口对于保证所有人都认同函数使用和返回值的类型来说是很重要
的。但是闭包并不用于这样暴露在外的接口:他们储存在变量中并被使用,不用命名他们或暴露给库的
用户调用。
闭包通常很短,并只关联于小范围的上下文而非任意情境。在这些有限制的上下文中,编译器能可靠的
推断参数和返回值的类型,类似于它是如何能够推断大部分变量的类型一样。
强制在这些小的匿名函数中注明类型是很恼人的,并且与编译器已知的信息存在大量的重复。

use std::thread;

use std::time::Duration;

fn generate_workout(intensity: u32, random_number: u32) {

let expensive_closure = |num: u32| -> u32 {
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)

);

}

}

}

fn main() {

let simulated_user_specified_value = 10;

let simulated_random_number = 7;

generate_workout(simulated_user_specified_value, simulated_random_number);

}

有了类型注解闭包的语法就更类似函数了。如下是一个对其参数加一的函数的定义与拥有相同行为闭包
语法的纵向对比。这里增加了一些空格来对齐相应部分。这展示了闭包语法如何类似于函数语法,除了
使用竖线而不是括号以及几个可选的语法之外:
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 ;
第一行展示了一个函数定义,而第二行展示了一个完整标注的闭包定义。第三行闭包定义中省略了类型
注解,而第四行去掉了可选的大括号,因为闭包体只有一行。这些都是有效的闭包定义,并在调用时产
生相同的行为。调用闭包要求 add_one_v3 和 add_one_v4 必须更够编译因为会根据其用途推断其类型。
闭包定义会为每个参数和返回值推断一个具体类型。例如,示例 13-8 中展示了仅仅将参数作为返
回值的简短的闭包定义。除了作为示例的目的这个闭包并不是很实用。注意其定义并没有增加任何类
型注解:如果尝试调用闭包两次,第一次使用 String 类型作为参数而第二次使用 u32,则会得到一个错误:

fn main() {

let example_closure = |x| x;
let s = example_closure(String::from(“hello”));
let n = example_closure(5);

}

示例 13-8:尝试调用一个被推断为两个不同类型的闭包
编译器给出如下错误:
$ 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);
| ^- help: try using a conversion method: .to_string()
| |
| expected struct String, found integer
For more information about this error, try rustc --explain E0308.
error: could not compile closure-example due to previous error
第一次使用 String 值调用 example_closure 时,编译器推断 x 和此闭包返回值的类型为 String。接着
这些类型被锁定进闭包 example_closure 中,如果尝试对同一闭包使用不同类型则会得到类型错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值