[英]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.