Improve Ch13

This commit is contained in:
Unisko PENG 2023-04-27 16:49:00 +08:00
parent 6ec8630461
commit c9782e2241

View File

@ -319,15 +319,15 @@ impl<T> Option<T> {
}
```
回顾到 `T` 就是表示 `Optoin``Some` 变种中,值类型的泛型。类型 `T` 也是 `unwrap_or_else` 函数的返回值类型:比如,在 `Option<String>` 上调用 `unwrap_or_else` 的代码,就得到一个 `String`
回顾到 `T` 就是表示 `Optoin``Some` 变种中,值类型的泛型。类型 `T` 也是 `unwrap_or_else` 函数的返回值类型:比如,在 `Option<String>` 上调用 `unwrap_or_else` 的代码,就得到一个 `String`
着,请注意这个 `unwrap_or_else` 函数有个额外的泛型参数 `F`。这个 `F` 类型为名为 `f` 的参数类型,而这个参数 `f`,则正是在调用 `unwrap_or_else` 时,所提供到的那个闭包。
下来,请留意 `unwrap_or_else` 函数有个额外的泛型参数 `F`。`F` 类型是名为 `f` 的参数类型,其正是调用 `unwrap_or_else` 时,咱们提供的闭包。
在这个泛型 `F` 上所指定的特质边界the trait bound`FnOnce() -> T`,就表示 `F` 必须能被调用一次、不取参数,并要返回一个 `T` 类型值。在特质边界中使用 `FnOnce`,表示 `unwrap_or_else` 只会调用 `f` 至多一次这样的约束。而在 `unwrap_or_else` 的函数体中,就可以看到在那个 `Option``Some` 时,`f` 不会被调用。在 `Option``None` 时,`f` 就会被调用一次。由于所有闭包都实现了 `FnOnce`因此 `unwrap_or_else` 就会接收最为广泛的闭包,进而有着其最大的灵活性
泛型 `F` 上所指定的特质边界the trait bound`FnOnce() -> T`表示 `F` 必须能被调用一次、不取参数,并要返回 `T` 类型值。在特质边界中使用 `FnOnce`,表示 `unwrap_or_else` 只会调用 `f` 最多一次的约束。在 `unwrap_or_else` 的主体中,咱们就可以看到,当 `Option``Some` 时,`f` 不会被调用。当 `Option``None` 时,`f` 就会被调用一次。由于所有闭包都实现了 `FnOnce``unwrap_or_else` 会接收最为广泛的闭包,而尽可能地灵活
> **注意**:函数也可以实现全部三个 `Fn` 特质。在打算执行的操作,不需要捕获环境中某个值时,就可以在需要某个实现了 `Fn` 特质处,使用某个函数名字而非闭包。比如,在某个 `Option<Vec<T>>` 值上,若这个值为 `None`,那么就可以调用 `unwrap_or_else(Vec::new)` 来获取到一个新的空矢量值。
> 注意:函数也可实现全部三个 `Fn` 特质。当咱们打算执行的操作,不需要捕获环境中的值时,便可在需要实现了 `Fn` 特质的物件处,使用函数名字而非闭包。比如,在 `Option<Vec<T>>` 值上,若该值为 `None`,那么咱们就可以调用 `unwrap_or_else(Vec::new)` 来获取到一个新的空矢量值。
现在来检视一下定义在切片上的那个标准库方法 `sort_by_key`,来看看其与 `unwrap_or_else` 有何区别,以及为何 `sort_by_key` 会使用 `FnMut` 而非 `FnOnce` 作为特质边界。其中的闭包,获得的是一个到正被处理切片中当前元素的引用形式的参数,并返回一个可被排序类型 `K` 的一个值。在想要以各个条目的某种特定属性,对切片进行排序时,此函数是有用的。在下面清单 13-7 中,就有一个 `Rectangle` 实例的清单,进而这里使用了 `sort_by_key`,来以 `width` 属性的升序对这些 `Rectangle` 实例加以排序:
现在咱们来看看定义在切片上的标准库方法 `sort_by_key`,以看出其与 `unwrap_or_else` 有何区别,及为何 `sort_by_key` 会使用 `FnMut` 而非 `FnOnce` 作为特质边界。闭包会得到一个到正被处理切片中,当前元素引用形式的参数,并返回可被排序的类型 `K` 的值。在咱们想要以各个条目的某种特定属性,对切片进行排序时,这个函数是有用的。在下面清单 13-7 中,咱们有着一个 `Rectangle` 实例的清单,且咱们使用了 `sort_by_key`,来以 `width` 属性的升序`Rectangle` 实例加以排序:
文件名:`src/main.rs`
@ -395,7 +395,7 @@ $ cargo run
]
```
`sort_by_key` 之所以被定义为取一个 `FnMut` 闭包,是由于他多次调用了这个闭包:对那个切片中的每个条目运行一次。那个闭包 `|r| r.width` 并不会捕获、修改,或是从其环境迁移任何东西,因此他就满足了 `FnMut` 这个特质边界的那些要求。
`sort_by_key` 被定义为取 `FnMut` 闭包的原因是,他会多次调用闭包:对切片中的每个条目调用一次。闭包 `|r| r.width` 不会捕获、修改,或从其环境迁迁出任何东西,因此其满足特质边界要求。
作为对照,下面清单 13-8 给出一个仅实现了 `FnOnce` 特质的闭包示例,正是因为该闭包将值迁移出了其环境。编译器不会允许咱们在 `sort_by_key` 下使用这个闭包: