简体   繁体   English

生锈和老迭代器模式

[英]Lifetime in rust and old iterator pattern

I've discovered Rust broke some old code and I was determined to fix it. 我发现Rust打破了一些旧代码,我决定修复它。 Sadly, it appears that lifetime references have changed quite a bit and something weird is happening. 可悲的是,似乎终身参考已经发生了很大的变化,并且发生了一些奇怪的事情。 Field Counter.data is irrelevant, it's just used to show that there is some data I use and it's reference to generic stuff. Field Counter.data是无关紧要的,它只是用来表明我使用的是一些数据,它是对泛型内容的引用。

Here is the code: 这是代码:

struct Counter <'c, T: 'c> {
    val: u32,
    data: &'c T
}

struct CounterIterator<'c, T:'c> {
    iter: &'c mut Counter<'c, T>,
    num: u32
}

impl<'r, T> Iterator<u32> for CounterIterator<'r, T> {
    fn next(&mut self) -> Option<u32> {
        if self.num  == 0 {
            None
        } else {
            self.num -= 1;
            self.iter.incr()
        }
    }
}

impl<'c, T> Counter <'c, T> {
    fn new(dataz: &'c T) -> Counter<'c, T> {
        Counter {
            val: 0u32,
            data: dataz
        }
    }

    fn incr(&mut self) -> Option<u32> {
        self.val += 1;
        println!("{}", self.val);
        Some(self.val)
    }

    fn iter(&'c mut self, num: u32) -> CounterIterator<'c, T> {
        CounterIterator {
            iter: self,
            num: num
        }
    }
}

fn main() {
    let val = 11u;
    let mut cnt = Counter::new(&val);
    for i in range(0,2u) {
        cnt.incr();
    }

    for i in cnt.iter(3) {

    }

    cnt.incr(); // <- commenting this out "fixes" the problem
    // Otherwise the error is 
    // note: previous borrow of `cnt` occurs here; the mutable borrow prevents 
    // subsequent moves, borrows, or modification of `cnt` until the borrow ends

}

What is the mistake here? 这里有什么错误? How do I make this so 'Iterator' idiom ends borrow by the time it exits the loop, instead at the end of block its defined? 我如何使这个'Iterator'成语在它退出循环时结束借用,而不是在它定义的块结束时? Also, what do explicit life times T:'c do? 另外,明确的生命时间T:'c做什么?

For record I'm trying to achieve Iterator API similar to str.chars() in usage. 为了记录,我正在尝试使用类似于str.chars() Iterator API。 If there is a saner way to do it, please let me know. 如果有更好的方法,请告诉我。

In fn iter , the &'c mut self ties the mutable borrow of self to the lifetime 'c of the Counter . fn iter中, &'c mut self关系的可变借self于终身'c的的Counter By the time you call cnt.incr() you can't borrow cnt because.... cnt is still alive (so the &'c mut self is still borrowing it). 当你调用cnt.incr()你不能借用cnt因为...... cnt仍然存活(所以&'c mut self仍在借用它)。

One possible way to make your code work is to move data in Counter instead of storing a borrowed reference to it, like this: 使代码工作的一种可能方法是在Counter移动data ,而不是存储借用的引用,如下所示:

struct Counter <T> {
    val: u32,
    data: T
}

If you want to keep data as a reference, another alternative is introducing a second named lifetime to the CounterIterator struct, so that the mutable borrow to Counter can live shorter than Counter itself. 如果你想保持数据作为参考,另一种选择是在CounterIterator结构中引入第二个命名生命周期,这样对Counter的可变借位可以比Counter本身短。

// we now have a shorter lifetime ('s) and a longer one ('l). This is 
// expressed to the compiler by the 'l: 's bound that says "'l lives 
// at least as long as 's"
struct CounterIterator<'s, 'l: 's, T: 'l> {
    iter: &'s mut Counter<'l, T>,
    num: u32
}

impl<'c,  T> Counter <'c, T> {
// ...
    // now the &mut self can live as long as CounterIterator, not necessarily as
    // long as Counter. This allows it to be released as soon as the iteration
    // is over and CounterIterator goes out of scope
    fn iter<'a>(&'a mut self, num: u32) -> CounterIterator<'a,'c, T> {
        CounterIterator {
            iter: self,
            num: num
        }
    }
}

For reference, since the language is still somewhat in flux: 作为参考,因为语言仍然有点不稳定:

$ rustc -v
rustc 0.12.0-pre-nightly (2e3858179 2014-09-03 00:51:00 +0000)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Rust:如何限制 Iterator::next() 的生命周期? - Rust: how to bound the lifetime of Iterator::next()? 如何为容器的Rust迭代器表达生命周期 - How to express lifetime for Rust iterator for a container Rust 迭代器遍历 Rc 层次结构的生命周期 - Lifetime for Rust Iterator to Walk a Hierarchy of `Rc`s 通过简单模式在 Rust 中关闭生命周期 - Closure lifetime in Rust through simple pattern 如何在Rust的装饰器模式中使用生命周期说明符? - How to use lifetime specifier in decorator pattern in Rust? Rust字符串生存期和迭代器适配器(生存期编译错误) - Rust string lifetimes and iterator adapters (lifetime compile error) 在递归函数中链接本地迭代器时出现 Rust Lifetime 问题 - Rust Lifetime issue when chaining local iterator in recursive function 在 Rust 中,返回具有生命周期依赖项的迭代器的最佳方法是什么? - In Rust, what is the best way to return an iterator that has a lifetime dependency? 尝试在返回迭代器的闭包内改变状态时,Rust 错误“无法推断借用表达式的适当生命周期” - Rust error "cannot infer an appropriate lifetime for borrow expression" when attempting to mutate state inside a closure returning an Iterator 如何在Rust中延长迭代器适配器内部临时变量的寿命? - How can I extend the lifetime of a temporary variable inside of an iterator adaptor in Rust?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM