正如标题所示,在 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>());
}
Run Code Online (Sandbox Code Playgroud)
// This compiles
fn main() {
let s = "Hello!";
println!("{}", &s.chars().rev().rev().collect::<String>());
}
Run Code Online (Sandbox Code Playgroud)
// This *does not* compile
fn main() {
let s = "Hello!";
println!("{}", &s.chars().rev().skip(1).rev().collect::<String>());
}
Run Code Online (Sandbox Code Playgroud)
最后一个无法编译:
// This compiles
fn main() {
let s = "Hello!";
println!("{}", &s.chars().rev().skip(1).collect::<String>());
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么会出现这种情况吗?
Val*_*tin 19
调用.chars()
返回一个Iterator
( Chars
) ,该 ( ) 实现了DoubleEndedIterator
,而 using 则.rev()
需要。
fn rev(self) -> Rev<Self>
where
Self: DoubleEndedIterator
Run Code Online (Sandbox Code Playgroud)
然后调用.skip()
会产生一个 new Iterator
( Skip
) ,只有DoubleEndedIterator
当Iterator
(在本例中Chars
)同时实现DoubleEndedIterator
和 时,它才会实现ExactSizeIterator
。
impl<I> DoubleEndedIterator for Skip<I>
where
I: DoubleEndedIterator + ExactSizeIterator
Run Code Online (Sandbox Code Playgroud)
然而,Chars
并没有实施ExactSizeIterator
。所以DoubleEndedIterator
没有实现Skip
. .rev()
所以现在第二次调用不再满足调用的要求。
该rev
方法返回一个名为的结构Rev<I>
,其中I
是您调用它的迭代器。
例如,
my_str.chars()
获取一个Chars
作为迭代器的结构。打电话.rev()
给你Rev<Chars>
。
.rev()
要求I
是 a DoubleEndedIterator
(这是有道理的,反转是通过从后到前迭代来完成的)。
该skip
方法返回一个名为的结构Skip<I>
,其中类似地,I
是您调用它的任何迭代器。
这可以在任何迭代器上调用(这是有道理的)。
然而,Skip<I>
仅DoubleEndedIterator
当I
实现DoubleEndedIterator
和 ExactSizeIterator
时才实现。
这意味着,我们只能.rev
调用Skip<I>
if I: DoubleEndedIterator + ExactSizeIterator
。
在我们查看您所写的内容之前,最后一点: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.
Run Code Online (Sandbox Code Playgroud)