据我所知,它DoubleEndedIterator适用于遍历一系列项目并可从任一端开始的迭代器.例如,(1..10)可以实现这个能够从1到10,或从10到1.但是,我有一种情况,将这个特性用于不迭代一系列事物的迭代器是有用的,但可以从同一个位置前进或后退,如下所示:
struct ExtremeIterator {
number: i32
}
impl Iterator for ExtremeIterator {
type Item = i32;
fn next(&mut self) -> Option<i32> {
let result = self.number;
self.number += 1;
Some(result)
}
}
impl DoubleEndedIterator for ExtremeIterator {
fn next_back(&mut self) -> Option<i32> {
let result = self.number;
self.number -= 1;
Some(result)
}
}
fn main() {
let iter = ExtremeIterator { number: 10 };
for i in iter.rev().take(5) {
println!("{}", i);
}
}
Run Code Online (Sandbox Code Playgroud)
所以这是我的问题:使用DoubleEndedIterator这种方式有什么语义错误吗?是否有某种原因使用它的目的与文档所说的不同?还有,有更好的方法来实现同样的目的吗?
首先,让我们在你的问题中澄清这个过去的评论:
例如,(1..10)可以实现这一点,从1到10,或从10到1.
1..10是类型的std::ops::Range<T>,它迭代到序列1,2,3,4,5,6,7,8,9无论你是从后面还是前面迭代它.从后面,你得到9,8,......,从前面得到,1,2,...... ; 它是一个开始包容,最终排他范围,也称为半开放范围.
如果你从前面然后从后面稍微迭代范围,它将停止在两端相遇的地方:
let mut range = 1..10;
for i in &mut range {
// Produce 1, 2, 3, 4, 5
// then break.
if i == 5 { break; }
}
for j in range.rev() {
// Produces 9, 8, 7, 6
}
Run Code Online (Sandbox Code Playgroud)
这显示了一个表现良好的双端迭代器是什么样的.(防锈围栏链接)
现在,对于DoubleEndedIterator"滥用" 的问题:
这是有问题的.
该DoubleEndedIterator文档是明确的:
范围迭代器,能够从两端生成元素
A
DoubleEndedIterator可以被认为是其中的双端齿轮next()和next_back()来自相同范围的排气元件,并且不能彼此独立地工作.
您必须将其理解为:无论是否使用next,next_back或者它们的组合,如果您跟踪它们(并跟踪它们来自哪个端点),任何遍历都必须生成相同范围的元素.
但是,有无限范围的情况......
在无限长的范围内,两端永远不会相遇.这种迭代器的一个例子是repeat.对于这个简单的例子可以很容易地看到二者为什么迭代器是无限的,怎么都next()和next_back()在逻辑上定义.
所以这是一个漏洞,您可以将迭代器的序列指定为无限长,尽管双重结束.我认为用我们的固定位宽整数来正确地实现这个接口是值得怀疑的.
即使有可疑的哲学动机,它也可能是一个非常混乱的迭代器,它无视合理的期望.我认为使用特征错误(比如说有一个迭代器的两个完全不同意的结尾)会很糟糕,但是如果有一个取之不尽的范围,你实际上不会破坏任何特征属性.