在迭代器特征中指定关联类型的生命周期

Chr*_*son 2 rust

我是 Rust 新手,我正在尝试找出在 Rust 中执行以下操作的最佳方法是什么:

struct ThingIterator {
    current: String,
    stop: String,
}

impl Iterator for ThingIterator {
    type Item = &str;
    fn next(&mut self) -> Option<&str> {
        if self.current == self.stop {
            return None;
        }
        // For testing
        self.current = self.stop;
        Some(&self.current)
    }
}

fn main() {
    let pi = ThingIterator {
        current: String::from("Ask"),
        stop: String::from("Zoo"),
    };
    println!("Number of things={}", pi.count());
}
Run Code Online (Sandbox Code Playgroud)

我的错误是:

error[E0106]: missing lifetime specifier
 --> src/main.rs:7:17
  |
7 |     type Item = &str;
  |                 ^ expected lifetime parameter

error: aborting due to previous error

Run Code Online (Sandbox Code Playgroud)

这是有道理的,我需要指定从 next() 返回的引用的有效时间。我猜测对于函数本身来说它很好,因为生命周期被省略了(不确定省略的共轭) - 但我以某种方式需要定义“type Item = &str”行的生命周期。

就我而言,只要“当前”有效,即与“自我”具有相同的生命周期,它就有效。

我没有在 Rust 书籍或其他文档中看到任何可以帮助我解决这个问题的内容。

PS 抱歉,如果我破坏了术语,我对 Rust 非常陌生。谢谢

SCa*_*lla 5

&mut self定义 type 时, in的生命周期next不在范围内Item,因此Item不能依赖于该生命周期。相反,通常使用ThingIterator保留引用而不是拥有的数据。如果仍然存在拥有数据的结构,您可能会实现IntoIteratorfor&OwnsData来转换为使用引用的类型。

// ThingIterator is now generic in the lifetime 'a
// and it holds references rather than owned Strings.
struct ThingIterator<'a> {
    current: &'a str,
    stop: &'a str,
}

impl<'a> Iterator for ThingIterator<'a> {
    // Now we can use the lifetime from ThingIterator here.
    type Item = &'a str;
    fn next(&mut self) -> Option<&'a str> {
        if self.current == self.stop {
            return None;
        }
        // For testing
        self.current = self.stop;
        Some(self.current)
    }
}

// Typically, you'll have a type that owns its data
// Like Vec<T>, HashSet<T>, etc.
struct OwnsData {
    current: String,
    stop: String,
}

impl OwnsData {
    // We'll have the traditional method that takes a reference
    // to self and returns an iterator over references into self.

    // Explicit lifetimes aren't needed, but it might help with understanding.
    // fn iter<'a>(&'a self) -> ThingIterator<'a> {

    fn iter(&self) -> ThingIterator {
        ThingIterator {
            current: &self.current,
            stop: &self.stop,
        }
    }
}

// Then, we'll implement IntoIterator for references to OwnsData
// using the OwnsData::iter method defined above.
// This is helpful because for loops and many iterator methods
// use IntoIterator to work.
impl<'a> IntoIterator for &'a OwnsData {
    // We'll be converting into ThingIterator
    type IntoIter = ThingIterator<'a>;
    type Item = &'a str;

    fn into_iter(self) -> ThingIterator<'a> {
        self.iter()
    }
}

fn main() {
    let pi = ThingIterator {
        current: "Ask",
        stop: "Zoo",
    };
    println!("Number of things={}", pi.count());

    // Alternatively, we could start with Strings
    // and use OwnsData
    let tau = OwnsData {
        current: "Ask".to_string(),
        stop: "Zoo".to_string(),
    };
    println!("Number of things={}", tau.iter().count());
}
Run Code Online (Sandbox Code Playgroud)

(操场)

也可以看看

PS你要找的词是“elided”。