我正在嘗試實作以下特征:
pub trait CentralMoment<Output = f32>
where
Output: Copy,
{
fn mean(&self) -> Output;
}
impl<T> CentralMoment for [T] {
fn mean(&self) -> f32 {
let sum: f32 = self.iter().sum();
sum / self.len() as f32
}
}
我的問題是線路let sum: f32 = self.iter().sum()。編譯器告訴我:
the trait bound `f32: Sum<&T>` is not satisfied
--> src/lib.rs:45:36
|
45 | let sum: f32 = self.iter().sum();
| ^^^ the trait `Sum<&T>` is not implemented for `f32`
|
help: consider extending the `where` bound, but there might be an alternative better way to express this requirement
|
42 | T: Copy, f32: Sum<&T>
但即使我嘗試包含f32: Sum<&T>我仍然遇到相同的錯誤。我在這里做錯了什么,我該如何解決這個問題?提前致謝,如果您需要任何進一步的說明,請告訴我。
uj5u.com熱心網友回復:
使用泛型的算術很棘手。正確設定所有約束和型別就像打地鼠游戲。每次修復錯誤時,都會彈出另一個錯誤。我不想直接跳到答案;如果我們一步一步地完成每個步驟,那就更好了。也就是說,如果您只想查看解決方案,它就在底部。
讓我們開始打吧。
1.復制數字
看看的實作者Sum。它們看起來像這樣:
impl Sum<f32> for f32
impl Sum<f64> for f64
impl Sum<i8> for i8
impl Sum<i16> for i16
impl Sum<i32> for i32
...
等等。
一般模式很明顯:
impl Sum<T> for T
它們都與您的代碼不匹配,因為它顯然試圖使用Sum<&T>. 我們需要擺脫參考,這樣Sum<&T>可以Sum<T>。
參考文獻從何而來?iter()迭代專案參考。這樣做是為了避免修改集合或其專案。
我們可以使用into_iter()直接迭代專案。不過,我們不要。into_iter()將集合轉換為迭代器。轉換...就像在破壞中一樣。它移動所有專案并在此程序中消耗集合。哎呀!
相反,讓我們使用以下命令復制專案copied():
當您有一個迭代器 over 時
&T,這很有用,但您需要一個迭代器 overT。
let sum: f32 = self.iter().copied().sum();
我們還需要一個T: Copy約束:
impl<T> CentralMoment for [T]
where
T: Copy,
這將錯誤更改為:
error[E0277]: the trait bound `f32: Sum<T>` is not satisfied
--> src/lib.rs:13:45
|
13 | let sum: f32 = self.iter().copied().sum();
| ^^^ the trait `Sum<T>` is not implemented for `f32`
操場
2.求和的結果是 T
當你總結一堆i32s 時,你會得到一個i32. 當你對一堆f64s求和時,你會得到一個f64. 這段代碼表示結果sum()will 是 an f32,但要真正通用,您應該將其稱為 a T。
let sum: T = self.iter().copied().sum();
現在的錯誤是:
error[E0277]: the trait bound `T: Sum` is not satisfied
--> src/lib.rs:13:43
|
13 | let sum: T = self.iter().copied().sum();
| ^^^ the trait `Sum` is not implemented for `T`
3.T必須是可總結的
我們可以解決這個要求T: Sum:
where
T: Copy Sum,
現在我們得到:
error[E0369]: cannot divide `T` by `f32`
--> src/lib.rs:16:13
|
16 | sum / self.len() as f32
| --- ^ ----------------- f32
| |
| T
操場
4.T必須被整除f32
我們很接近,對吧?讓我們要求它T可以被f32s整除:
where
T: Copy Sum Div<f32>,
你開心嗎,編譯器?
error[E0308]: mismatched types
--> src/lib.rs:17:9
|
15 | fn mean(&self) -> f32 {
| --- expected `f32` because of return type
16 | let sum: T = self.iter().copied().sum();
17 | sum / self.len() as f32
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `f32`, found associated type
|
= note: expected type `f32`
found associated type `<T as Div<f32>>::Output`
= help: consider constraining the associated type `<T as Div<f32>>::Output` to `f32`
操場
不,當然不。很好,很好,現在呢?
5. 分部必須回傳一個 f32
好吧,我們要求它T可以被 整除f32。不過,我們還沒有告訴它結果是什么型別。運算元型別和結果型別并非相同。他們可以不同。Rust 非常靈活。
我們需要對::Output操作進行約束。讓我們要求輸出也是一個f32:
where
T: Copy Sum Div<f32, Output = f32>,
結果:
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized debuginfo] target(s) in 0.91s
哈利路亞!公主不在另一個城堡里。
操場
解決方案
use std::iter::Sum;
use std::ops::Div;
pub trait CentralMoment<Output = f32>
where
Output: Copy,
{
fn mean(&self) -> Output;
}
impl<T> CentralMoment for [T]
where
T: Copy Sum Div<f32, Output = f32>,
{
fn mean(&self) -> f32 {
let sum: T = self.iter().copied().sum();
sum / self.len() as f32
}
}
操場
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/384264.html
