Tim*_*mmm 16 types type-inference rust
此代码有效:
fn main() {
let a: i32 = (1i32..10).sum();
let b = a.pow(2);
}
Run Code Online (Sandbox Code Playgroud)
如果我i32
从中删除类型a
,那么我收到此错误:
rustc 1.13.0 (2c6933acc 2016-11-07)
error: the type of this value must be known in this context
--> <anon>:3:13
|
5 | let b = a.pow(2);
| ^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
我原以为Rust会(1i32..10)
变成i32
迭代器然后sum()
知道返回一个i32
.我错过了什么?
Chr*_*son 15
sum
定义方式,返回值是开放式的; 多种类型可以实现特征Sum<i32>
.这是一个a
使用不同类型的示例,两者都编译:
#[derive(Clone, Copy)]
struct Summer {
s: isize,
}
impl Summer {
fn pow(&self, p: isize) {
println!("pow({})", p);
}
}
impl std::iter::Sum<i32> for Summer {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = i32>,
{
let mut result = 0isize;
for v in iter {
result += v as isize;
}
Summer { s: result }
}
}
fn main() {
let a1: i32 = (1i32..10).sum();
let a2: Summer = (1i32..10).sum();
let b1 = a1.pow(2);
let b2 = a2.pow(2);
}
Run Code Online (Sandbox Code Playgroud)
由于两种结果类型都是可能的,因此无法推断类型,必须通过turbofish(sum::<X>()
)或表达式(let x: X = ...sum();
)的结果显式指定.
然后
sum()
知道返回一个i32
这是关键的缺失点.虽然"输入"类型已经知道(它必须是Iterator
为了sum
甚至可用而实现的),但"输出"类型非常灵活.
fn sum<S>(self) -> S
where
S: Sum<Self::Item>,
Run Code Online (Sandbox Code Playgroud)
它返回一个S
必须实现的泛型类型Sum
.S
不必匹配Self::Item
.因此,编译器要求您指定要汇总的类型.
为什么这有用?从标准库中查看这两个示例实现:
impl Sum<i8> for i8
impl<'a> Sum<&'a i8> for i8
Run Code Online (Sandbox Code Playgroud)
那就对了!你可以总结一个迭代器u8
或迭代器&u8
!如果我们没有这个,那么这段代码不起作用:
fn main() {
let a: i32 = (0..5).sum();
let b: i32 = [0, 1, 2, 3, 4].iter().sum();
assert_eq!(a, b);
}
Run Code Online (Sandbox Code Playgroud)
作为bluss指出,我们可以通过具有实现这一目标相关联的类型,其将配合u8 -> u8
和&'a u8 -> u8
.
如果我们只有一个关联的类型,那么目标总和类型将始终是固定的,我们将失去灵活性.请参阅何时使用关联类型与泛型类型?更多细节.
作为一个例子,我们也可以Sum<u8>
为我们自己的类型实现.在这里,我们总结了u8
s,但增加了我们总结的类型的大小,因为它可能总和会超过a u8
.此实现是标准库中现有实现的补充:
#[derive(Debug, Copy, Clone)]
struct Points(i32);
impl std::iter::Sum<u8> for Points {
fn sum<I>(iter: I) -> Points
where
I: Iterator<Item = u8>,
{
let mut pts = Points(0);
for v in iter {
pts.0 += v as i32;
}
pts
}
}
fn main() {
let total: Points = (0u8..42u8).sum();
println!("{:?}", total);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1337 次 |
最近记录: |