通过在字符串文字上调用`chars`方法产生的类型/特征是什么?

时间:2017-12-02 19:27:58

标签: rust

考虑这段代码:

struct Collector<T>
where
    T: Iterator<Item = char>,
{
    current: u32,
    right_neighbour: u32,
    counter: usize,
    iterator: T,
}

impl<T: Iterator<Item = char>> Collector<T> {
    fn next(&self) -> u32 {
        self.iterator
            .next()
            .expect("failed to get next digit!")
            .to_digit(10)
            .expect("failed to prase char as digit!")
    }

    fn collect(&self) {
        self.current = self.right_neighbour;
        self.right_neighbour = self.next();
        self.counter = self.counter + 1;
    }

    fn initialize<U>(iterator: U) -> Collector<U>
    where
        U: Iterator<Item = char>,
    {
        let mut collector = Collector {
            current: 0,
            right_neighbour: 0,
            counter: 0,
            iterator: iterator,
        };

        collector.collect();

        collector
    }
}

fn main() {
    let numstr = "1111";

    let mut collector = Collector::initialize(numstr.chars().cycle().peekable());
}

它会产生类型不匹配错误:

error[E0284]: type annotations required: cannot resolve `<_ as std::iter::Iterator>::Item == char`
  --> src/main.rs:46:25
   |
46 |     let mut collector = Collector::initialize(numstr.chars().cycle().peekable());
   |                         ^^^^^^^^^^^^^^^^^^^^^
   |
   = note: required by `<Collector<T>>::initialize`

numstr.chars().cycle().peekable()的类型是什么?编译器告诉我它的完整类型是:

std::iter::Peekable<std::iter::Cycle<std::str::Chars<'_>>>

我知道我不能在我的结构/函数的定义中使用该类型,因为it doesn't have an explicit lifetime...

如何正确编写此代码?

1 个答案:

答案 0 :(得分:1)

  

通过在字符串文字上调用chars方法产生的类型/特征是什么?

documentation for str::chars确切地告诉您它的类型:

fn chars(&self) -> Chars
  

它产生类型不匹配错误

是的,因为您没有指定具体类型T应该是什么。您已经引入了一个完全独立的泛型类型U,并且没有引用T的参数或返回类型。编译器没有用于推断T是什么的上下文。

  

如何正确编写此代码?

删除无用的额外类型参数:

struct Collector<T>
where
    T: Iterator<Item = char>,
{
    current: u32,
    right_neighbour: u32,
    counter: usize,
    iterator: T,
}

impl<T: Iterator<Item = char>> Collector<T> {
    fn new(iterator: T) -> Collector<T> {
        let mut collector = Collector {
            current: 0,
            right_neighbour: 0,
            counter: 0,
            iterator: iterator,
        };

        collector.collect();

        collector
    }

    fn collect(&self) {
        unimplemented!()
    }

    fn next(&self) -> u32 {
        unimplemented!()
    }
}

fn main() {
    let numstr = "1111";

    let mut collector = Collector::new(numstr.chars().cycle().peekable());
}

我删除了nextcollect的实现,因为它们有其他不相关的错误,我无需修复。我还将initialize重命名为new,因为new是缺少多个构造函数时的标准构造函数名称。

值得注意的是,peekable在这里的使用完全没用。泛型类型T不知道可以调用peek,因为没有适当的特征限制。

  

因为它没有明确的生命周期

您不必关心生命周期所涵盖的生命周期。如果你的类型需要知道它是可以窥视的,那就把它放在你的结构中:

struct Collector<T>
where
    T: Iterator<Item = char>,
{
    // ...
    iterator: std::iter::Peekable<T>,
}

impl<T: Iterator<Item = char>> Collector<T> {
    fn new(iterator: T) -> Collector<T> {
        let mut collector = Collector {
            // ...
            iterator: iterator.peekable(),
        };

        // ...
    }

    // ...
}

fn main() {
    // ...
    let mut collector = Collector::new(numstr.chars().cycle());
}