簡體   English   中英

如何使用Iterator特征構建通用API

[英]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);
    }
}

如果我想將它與HashSetHashMap一起使用,顯然這不足。

所以,我試過這個:

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);
    }
}

游戲圍欄(也用於查看冗長的編譯器錯誤)

http://is.gd/EYIK11

不幸的是,這似乎也沒有做到這一點。 我錯過了什么?

更好的是,你可以做到

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM