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

标签 iterator rust traits lifetime

我想为包含 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, 2, 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

chars 迭代器应该与 StringStruct::system_string 具有相同的生命周期,但我不知道如何表达这一点,也不知道这种方法是否可行。

最佳答案

要回答您提出的问题,我建议您impl IntoIterator for &StringStruct (引用 StringStruct 而不是直接结构)。代码如下所示:

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);
    }
}

还有一个小注释:一个明确的 return不必要的时候在 Rust 中被认为是糟糕的风格。通过删除 return 更好地坚持规则并编写惯用代码只要有可能 ;-)

关于iterator - 使用修改后的 `Chars` 迭代器时生命周期参数的数量错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40057904/

相关文章:

rust - 使用生命周期参数为特征分离可变借位

c++ - 能否重新插入一个元素 "re-validate"迭代器?

rust - 在 Rust FFI 中解析联合结构

functional-programming - 为什么我不能反转迭代器两次以获得向量的最后两个数字?

iterator - 具有返回迭代器的函数的特征

generics - 如何为对特征本身的关联类型的引用编写特征绑定(bind)?

c++ - 接口(interface)方法的实现

python - 我如何使用 GeneratorExit?

c++ - 返回 C++ 迭代器引用

rust - 在 Rust 中连接字节、字符串和比较