[英]How do I use the Iterator trait to build generic APIs
我可能沒有看到森林的樹木,但我想知道我如何設計我的方法,以對抗硬集合類型,而不是反對迭代器。 考慮這種方法。
pub fn print_strings(strings: Vec<String>) {
for val in strings.iter() {
println!("{}", val);
}
}
如果我想將它與HashSet
或HashMap
一起使用,顯然這不足。
所以,我試過這個:
use std::collections::*;
fn main () {
let strings = vec!("Foo", "Bar");
let mut more_strings = HashMap::new();
more_strings.insert("foo", "bar");
more_strings.insert("bar", "foo");
print_strings(&strings.iter());
print_strings(&more_strings.values())
}
fn print_strings(strings: &Iterator<Item=&str>) {
for val in strings {
println!("{}", val);
}
}
游戲圍欄(也用於查看冗長的編譯器錯誤)
不幸的是,這似乎也沒有做到這一點。 我錯過了什么?
更好的是,你可以做到
fn print_strings<Iterable>(strings: Iterable)
where Iterable: IntoIterator,
Iterable::Item: AsRef<str>
{
for val in strings {
println!("{}", val.as_ref());
}
}
(Kudos Shepmaster的改進。)
這意味着您可以使用&mut Iterator
進行動態調度或具體迭代器或靜態分派的集合類型。 此外,迭代器類型可以是任何可以簡單地轉換為&str
,包括但不限於&str
, &&str
和even String
。
print_strings(&strings);
print_strings(strings.iter().map(|s| s.to_owned()));
print_strings(vec![&&&&"xyz"]);
print_strings(strings);
print_strings(more_strings.values());
當你在Vec<T>
上調用.iter()
時,你得到一個Iterator<Item=&T>
。 所以當你在Vec<&str>
上調用.iter()
時,你得到一個Iterator<Item=&&str>
,而不是Iterator<Item=&str>
。 您應該查看Iterator
的.cloned()
方法,它應該有助於解決您的問題。
另外,請注意,為了遍歷迭代器,您必須能夠對其進行變異(擁有迭代器或對其進行可變引用)。 因此,只有一個不可變的引用是有點無用的。 我建議將迭代器值移動到print_strings而不是通過引用傳遞它。 如果你想為此使用trait對象,可以使用Box
,但是將print_strings作為通用函數可能更容易。
圍欄
所以第一件事就是你期待Iterator<Item=&str>
,但實際上它是Iterator<Item=&&str>
。
然后,你試圖調用.iter()
,但Iterator
沒有這個方法。 你可以簡單地刪除.iter()
調用和接收(和發送OFC) &mut Iterator<...>
以獲得for
循環工作( for
循環需要的東西,實現IntoIterator
,並&mut Iterator
是什么東西)。
添加生命周期,你就完成了! :)
另外,我建議使用靜態調度。 您可以在我提供的示例中看到它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.