拉链两条链后如何反转

时间:2015-06-13 15:34:58

标签: rust

我有以下不编译的代码。

fn main() {
  let a =
    "123"
    .chars()
    .chain("4566".chars())
    .zip(
        "bbb"
        .chars()
        .chain("yyy".chars()))
    .rev()
    .map(|x, y| y)
    .collect::<String>();
  println!("Hello, world! {}", a);
}

得到如下错误:

src/main.rs:37:10: 37:15 error: the trait `core::iter::ExactSizeIterator` is not implemented for the type `core::iter::Chain<core::str::Chars<'_>, core::str::Chars<'_>>` [E0277]
src/main.rs:37         .rev()
                        ^~~~~
src/main.rs:37:10: 37:15 error: the trait `core::iter::ExactSizeIterator` is not implemented for the type `core::iter::Chain<core::str::Chars<'_>, core::str::Chars<'_>>` [E0277]
src/main.rs:37         .rev()
                        ^~~~~
src/main.rs:38:10: 38:23 error: type `core::iter::Rev<core::iter::Zip<core::iter::Chain<core::str::Chars<'_>, core::str::Chars<'_>>, core::iter::Chain<core::str::Chars<'_>, core::str::Chars<'_>>>>` does not implement any method in scope named `map`
src/main.rs:38         .map(|x, y| y)

我的理解是rev()方法在Iterator中定义为实现特征的DoubleEndedIterator

fn rev(self) -> Rev<Self> where Self: DoubleEndedIterator { ... }

同样Zip实现了这个特性:

impl<A, B> DoubleEndedIterator for Zip<A, B> where B: DoubleEndedIterator + ExactSizeIterator, A: DoubleEndedIterator + ExactSizeIterator

问题是Chain没有实现ExactSizeIterator。但是我该如何解决这个问题?

我尝试为两个链添加.take()以将类型转换为实现Take的{​​{1}},但请勿实现ExactSizeIterator

请注意,这是一个简化的示例。实际上,我不能先反转两个链,然后再拉链。

1 个答案:

答案 0 :(得分:8)

您正在寻找以下impl(剧透:它不存在):

impl<A, B> ExactSizeIterator for Chain<A, B>
  where A: ExactSizeIterator, B: ExactSizeIterator { ... }

ExactSizeIterator必须只实现一种方法len(&self)。因此,假设实现背后的想法是将两个长度相加以便chain_a_b.len() == a.len() + b.len()

reason it doesn't exist是Rust无法保证此添加(usize + usize)不会溢出。因此它禁止它。听起来有点严格,但不幸的是,这是现在的现状。

更糟糕的是:即使这个impl确实存在,你也会遇到Chars不是ExactSizeIterator的事实,所以它仍然无效。

替代方案(可能不是唯一的方法)是将链条收集到矢量中。由于内存分配不好,但如果它不是一个性能瓶颈,那么值得进行权衡。