我決定嘗試在Rust中使用空白實作做一個trait,而要實作的測驗方法是一個trait,它可以將迭代器的argmax和元素一起回傳。現在的實作是
use num::Bounded;
trait Argmax< T> {
fn argmax(self) -> (usize, T) 。
}
impl<I, T> Argmax<T> for I
where
I: Iterator<Item = T> 。
T: std::cmp::PartialOrd Bounded,
{
fn argmax(self) ->/span> (usize, T) {
self.enumerate()
.fold((0, T::min_value()), |(i_max, val_max), (i, val) | {
if val >= val_max {
(i, val)
} else {
(i_max, val_max)
}
})
}
}
用這段代碼進行測驗
fn main() {
let v = vec! [1. , 2. , 3. , 4. , 2. , 3. ] 。
println!("v: {:?}", v)。
let (i_max, v_max) = v.iter().copy().argmax()
println!("i_max: {}
v_max: {}", i_max, v_max)。)
作業,而
fn main() {
let v = vec! [1. , 2. , 3. , 4. , 2. , 3. ] 。
println!("v: {:?}", v)。
let (i_max, v_max) = v.iter().argmax() 。
println!("i_max: {}
v_max: {}", i_max, v_max)。)
無法編譯,并出現了這些錯誤:
-->/span> src/main.rs:27:35
|
27 | let (i_max, v_max) = v.iter().argmax()。
| ^^^^^^ 方法不能在`std::slice::Iter<'_, {float}>`上呼叫,因為沒有滿足trait bounds。
|
=注意:以下trait bounds未被滿足。
`<&std::slice::Iter<'_, {float}> as Iterator> :Item = _`.
這是`&std::slice::Iter<'_, {float}>所要求的。Argmax<_>`。
`&std::slice::Iter<'_, {float}> 。Iterator`。
這是`&std::slice::Iter<'_, {float}>所要求的。Argmax<_>`。
錯誤:由于之前的錯誤而中止
關于這個錯誤的更多資訊,try `rustc --explain E0599`。
我認為這個問題源于.iter()在參考上回圈,而.iter().copy()在實際值上回圈,但我仍然無法理解這個錯誤資訊以及如何使其通用并在參考上回圈作業。
uj5u.com熱心網友回復:
我還是無法理解這個錯誤資訊
我還是無法理解這個錯誤資訊
我還是無法理解這個錯誤資訊。
不幸的是,這個錯誤資訊很神秘,因為它沒有告訴你<&std::slice::Iter<'_, {float}> as Iterator>:Item 是,這是關鍵的事實 - 只是它不是什么。(可能這并不能幫助我們,{float},一個尚未選擇的數字型別,被卷入其中。我也不確定&在那里做什么,因為這里沒有涉及到對迭代器的參考。
然而,如果你查找std::slice::Iter<'a, T>的檔案,你會發現其專案型別是&'a T,所以在這種情況下,&'a {float}。
這告訴你你已經知道的事情:迭代器是在參考之上。不幸的是,這個錯誤資訊并沒有告訴你問題的其余部分。但是如果我查看num::Bounded的檔案,我發現,不出所料,Bounded并沒有為對數字的參考實作。這是不足為奇的,因為參考必須是存在于記憶體中的值,所以構建不借用某些現有資料結構的參考可能很棘手,甚至不可能。(我認為在這種情況下,這可能是可行的,但是num還沒有實作。)
以及如何使它成為通用的,并在參考中回圈作業。
只要你選擇使用Bounded trait,這是不可能的,因為Bounded沒有對原始數的參考進行實作,并且不可能為&T和T提供兩種不同的空白實作。
(你可以為你自己的一個型別Bounded實作MyWrapper<f32>,以及對它的參考,但是用戶必須處理這個包裝器。)
有一些選擇。
這里有一些選擇:
保留你目前擁有的代碼,并忍受撰寫
.copied()的需要。在其他迭代器中出現這種情況并不罕見--不要為了避免一個額外的函式呼叫而使代碼變得更加繁瑣。寫一個
argmax()的版本,回傳型別為Option<(usize, T)>,當迭代器為空時產生None。那么,就不需要使用Bounded,代碼將只在PartialEq的約束下作業。而且,當迭代器為空時,它將不會回傳一個無意義的索引和值--這在Rust代碼中通常被認為是一種美德。如果(0, T::min_value())對他們的應用來說是一個合適的答案,那么呼叫者可以一直使用.unwrap_or_else()。寫一個版本的
argmax(),它需要一個單獨的初始值,而不是使用T::min_value()。
uj5u.com熱心網友回復:
PartialOrd是為參考實作的;這里的問題是num::Bounded不是。如果你讓argmax函式遵循當迭代器為空時回傳None的慣例(就像Iterator::max>那樣),你可以完全擺脫對num::Bounded特質的依賴:
fn argmax(self) -> Option<(usize, T) > {
let mut enumerated = self.enumerate() 。
enumerated.next().map(move|first| {
enumerated.fold(first, |(i_max, val_max), (i, val)| {
if val >= val_max {
(i, val)
} else {
(i_max, val_max)
}
})
})
}
這也允許Argmax在自定義(潛在的)非數字可比型別的迭代器上實作
作為一個旁觀者,您可能想要轉換 Argmax 特質以使用關聯型別而不是通用型別,只是 像 Iterator。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/330164.html
標籤:
上一篇:安卓系統從郵件中的深度鏈接
