作为标题,在Rust中,.rev().rev()
工作,.rev().skip(1)
工作,但.rev().skip(1).rev()
不工作。下面是演示:
// This compiles
fn main() {
let s = "Hello!";
println!("{}", &s.chars().rev().skip(1).collect::<String>());
}
// This compiles
fn main() {
let s = "Hello!";
println!("{}", &s.chars().rev().rev().collect::<String>());
}
// This *does not* compile
fn main() {
let s = "Hello!";
println!("{}", &s.chars().rev().skip(1).rev().collect::<String>());
}
最后一个不编译:
error[E0277]: the trait bound `Chars<'_>: ExactSizeIterator` is not satisfied
--> src/main.rs:3:45
|
3 | println!("{}", &s.chars().rev().skip(1).rev().collect::<String>());
| ^^^ the trait `ExactSizeIterator` is not implemented for `Chars<'_>`
|
= note: required because of the requirements on the impl of `ExactSizeIterator` for `Rev<Chars<'_>>`
= note: required because of the requirements on the impl of `DoubleEndedIterator` for `Skip<Rev<Chars<'_>>>`
error[E0599]: the method `collect` exists for struct `Rev<Skip<Rev<Chars<'_>>>>`, but its trait bounds were not satisfied
--> src/main.rs:3:51
|
3 | println!("{}", &s.chars().rev().skip(1).rev().collect::<String>());
| ^^^^^^^ method cannot be called on `Rev<Skip<Rev<Chars<'_>>>>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`Skip<Rev<Chars<'_>>>: DoubleEndedIterator`
which is required by `Rev<Skip<Rev<Chars<'_>>>>: Iterator`
`Rev<Skip<Rev<Chars<'_>>>>: Iterator`
which is required by `&mut Rev<Skip<Rev<Chars<'_>>>>: Iterator`
<一口>操场一口>
有人能解释一下为什么会这样吗?
调用.chars()
返回实现DoubleEndedIterator
的Iterator
(Chars
),而使用.rev()
则需要。
fn rev(self) -> Rev<Self>
where
Self: DoubleEndedIterator
然后调用.skip()
产生一个新的Iterator
(Skip
),其中只有如果Iterator
(本例中为Chars
)同时实现DoubleEndedIterator
和ExactSizeIterator
,则实现DoubleEndedIterator
。
impl<I> DoubleEndedIterator for Skip<I>
where
I: DoubleEndedIterator + ExactSizeIterator
但是,Chars
没有实现ExactSizeIterator
。所以DoubleEndedIterator
没有为Skip
实现。所以现在调用.rev()
的要求不再适用于第二次调用。
rev
方法返回一个名为Rev<I>
的结构体,其中I
是你在其上调用的迭代器。
例如,
my_str.chars()
得到一个Chars
结构体,它是一个迭代器。呼叫.rev()
转到Rev<Chars>
.rev()
要求I
是DoubleEndedIterator
(这是有意义的,反转只需从后到前迭代即可完成)。
skip
方法返回一个名为Skip<I>
的结构体,类似地,I
是你调用它的迭代器。
可在任何迭代器上调用(这是有意义的)。
然而如果I
实现了DoubleEndedIterator
和ExactSizeIterator
,则Skip<I>
只实现了DoubleEndedIterator
。
这意味着,如果I: DoubleEndedIterator + ExactSizeIterator
,我们只能在Skip<I>
上调用.rev
。
在我们看你写的东西之前,最后一点:Chars
实现了DoubleEndedIterator
,但不实现ExactSizeIterator
,因为字符在utf8编码时是可变长度的。
看一看这整件事:
s
.chars() // DoubleEndedIterator
.rev() // DoubleEndedIterator
.skip() // Doesn't implement DoubleEndedIterator because it doesn't implement ExactSizeIterator
.rev() // Err, we need DoubleEndedIterator here.
两个rev()
无论如何是一个noop,Iterator
是懒惰的,所以第二个rev()
取消了第一个,除非迭代器在两个调用之间被消耗。
要跳过迭代器的最后一项,然后按顺序收集,我将这样做:
use std::iter::{DoubleEndedIterator, FromIterator, Iterator};
fn collect_rev_nth_n_rev<I, C>(items: I, n: usize) -> C
where
I: DoubleEndedIterator,
C: FromIterator<<I as Iterator>::Item>,
{
let mut iter = items.rev();
iter.nth(n);
iter.rev().collect()
}
fn main() {
let result: String = collect_rev_nth_n_rev("Hello!".chars(), 0);
assert_eq!("Hello", result);
}
nth()
通常是很好的优化。