我有这个结构:
struct RepIter<T> {
item: T
}
我想为它实现Iterator
,以便每次都返回对item
的引用:
impl<T> Iterator for RepIter<T> {
type Item = &T;
fn next(&mut self) -> Option<Self::Item> {
return Some(&self.item);
}
}
这不会编译,因为必须为type Item = &T;
指定生命周期。正在寻找一种方法,我找到了this question。第一种解决方案似乎并不适用,因为我实现了预先存在的特征。试图直接复制第二个解决方案我得到这样的东西:
impl<'a, T> Iterator for &'a RepIter<T> {
type Item = &'a T;
fn next(self) -> Option<&'a T> {
return Some(&self.item);
}
}
这不起作用,因为我需要一个可变的self
作为next
的参数。我能够编译它的唯一方法就是这样写:
impl<'a, T> Iterator for &'a RepIter<T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
return Some(&self.item);
}
}
但现在self
是对引用的引用,对吧?我不知道如何在next
的实例上致电RepIter
。例如,这不起作用:
fn main() {
let mut iter: RepIter<u64> = RepIter { item: 5 };
let res = iter.next();
}
这让我觉得我的特质实现可以用更好的方式编写。
答案 0 :(得分:3)
在设计迭代器时,为集合和迭代器提供不同类型的集合通常很有用。通常,集合将拥有数据,迭代器将从集合中借用。集合类型通常实现IntoIterator
并且不实现Iterator
。这意味着创建迭代器分两步进行:我们需要先创建集合,然后从集合中创建迭代器。
这是一个将RepIter
类型转换为集合的解决方案。我将使用Shepmaster的命题来使用iter::repeat
来生成迭代器。
use std::iter::{self, Repeat};
struct RepIter<T> {
item: T,
}
impl<T> RepIter<T> {
// When IntoIterator is implemented on `&Self`,
// then by convention, an inherent iter() method is provided as well.
fn iter(&self) -> Repeat<&T> {
iter::repeat(&self.item)
}
}
impl<'a, T> IntoIterator for &'a RepIter<T> {
type Item = &'a T;
type IntoIter = Repeat<&'a T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
fn main() {
let iter: RepIter<u64> = RepIter { item: 5 };
let res = iter.iter().next();
println!("{:?}", res);
let res = iter.iter().fuse().next();
println!("{:?}", res);
let res = iter.iter().by_ref().next();
println!("{:?}", res);
}
答案 1 :(得分:2)
正如Shepmaster所链接的question中所讨论的那样,这有点棘手,因为你真的想要改变next()
的类型,但是你不能因为它而不是部分特征。但是有几种方法可以解决这个问题。
对代码进行微小的更改,您只需使用Iterator
上的&'a RepIter<T>
实现:
pub fn main() {
let mut iter = RepIter { item: 5 };
let res = (&iter).next();
}
虽然有点不愉快。
另一种看待这种情况的方法是更改商品的所有权。如果已经借用了,那么你可以很好地匹配所有类型:
struct RepIter<'a, T: 'a> {
item: &'a T,
}
impl<'a, T> Iterator for RepIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
Some(&self.item)
}
}
pub fn main() {
let val: u64 = 5;
let mut iter = RepIter { item: &val };
let res = iter.next();
}
答案 2 :(得分:2)
我建议您将代码编写为:
Iterator
我还不太了解的一件事是你的现有代码几乎有效,但只适用于某些self
方法;那些按值struct RepIter<T> {
item: T,
}
impl<'a, T> Iterator for &'a RepIter<T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
return Some(&self.item);
}
}
fn main() {
let iter: RepIter<u64> = RepIter { item: 5 };
// Works
let res = iter.fuse().next();
println!("{:?}", res);
// Doesn't work
let res = iter.by_ref().next();
println!("{:?}", res);
}
而不是参考的那些!
var customerRecord = r.Load({
"type": r.Type.CUSTOMER,
"id": recordId,
"isDynamic": true
});
可能会发生一些有趣的互动。