使用修改后的`Chars`迭代器时,生命周期参数的数量错误

我想为包含String的结构实现IntoIterator特征.迭代器基于chars()迭代器,应该计算’1’字符并累积结果.这是我到目前为止的简化版本:

use std::iter::Map;
use std::str::Chars;

fn main() {
    let str_struct = StringStruct { system_string: String::from("1101") };
    for a in str_struct {
        println!("{}", a);
    }
}

struct StringStruct {
    system_string: String
}

impl IntoIterator for StringStruct {
    type Item = u32;
    type IntoIter = Map<Chars, Fn(char) -> u32>;

    fn into_iter(self) -> Self::IntoIter {
        let count = 0;
        return self.system_string.chars().map(|c| match c {
            Some('1') => {
                count += 1;
                return Some(count);
            },
            Some(chr) => return Some(count),
            None => return None
        });
    }
}

预期产量:1,2,3,3

这失败了:

error[E0107]: wrong number of lifetime parameters: expected 1, found 0
  --> src/main.rs:17:25
   |
17 |     type IntoIter = Map<Chars, Fn(char) -> u32>;
   |                         ^^^^^ expected 1 lifetime parameter

字符迭代器应该与StringStruct :: system_string具有相同的生命周期,但我不知道如何表达这个或者这种方法是否可行.

最佳答案
为了回答你提出的问题,我建议为了& StringStruct(直接引用StringStruct而不是结构)来实现IntoIterator.代码如下所示:

impl<'a> IntoIterator for &'a StringStruct {
    type Item = u32;
    type IntoIter = Map<Chars<'a>, Fn(char) -> u32>;
    // ...
}

但是,您会注意到之后有更多不同来源的错误.弹出的下一个错误是Fn(char) – > u32在编译时没有常量.

问题是您尝试通过编写Fn(char) – >来命名闭包的类型. U32.但这不是你的闭包的类型,而只是闭包实现的特征.无法命名闭包的类型(有时称为“Voldemort类型”).

这意味着,您现在无法指定Map< _,_>的类型.宾语.这是一个已知的问题;最近接受的impl Trait-RFC可能会为这样的案例提供一种解决方法.但是现在,这是不可能的,对不起.

那么如何解决呢?您需要创建自己的类型来实现Iterator并使用它而不是Map< _,_>.请注意,您仍然可以使用Chars迭代器.这是完整的解决方案:

struct StringStructIter<'a> {
    chars: Chars<'a>,
    count: u32,
}

impl<'a> Iterator for StringStructIter<'a> {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
         self.chars.next().map(|c| {
            if c == '1' {
                self.count += 1;
            }
            self.count
        })
    }
}

impl<'a> IntoIterator for &'a StringStruct {
    type Item = u32;
    type IntoIter = StringStructIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
         StringStructIter {
             chars: self.system_string.chars(),
             count: 0,
         }
    }
}

fn main() {
    let str_struct = StringStruct { system_string: String::from("1101") };
    for a in &str_struct {
        println!("{}", a);
    }
}

而且只是一个小小的注释:在不必要时显式返回被认为是Rust中的坏风格.通过尽可能删除返回,更好地坚持规则并编写惯用代码;-)

转载注明原文:使用修改后的`Chars`迭代器时,生命周期参数的数量错误 - 代码日志