简体   繁体   English

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

[英]Wrong number of lifetime parameters when using a modified `Chars` iterator

I want to implement the IntoIterator trait for a struct containing a String . 我想为包含String的结构实现IntoIterator特性。 The iterator is based on the chars() iterator, is supposed to count the '1' chars and accumulate the result. 迭代器基于chars()迭代器,应该计算'1'字符并累加结果。 This is a simplified version of what I got so far: 这是到目前为止我得到的简化版本:

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

Expected output: 1, 2, 2, 3 预期输出: 1, 2, 2, 3

This fails with: 失败的原因是:

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

The chars iterator should have the same lifetime as the StringStruct::system_string , but I have no idea how to express this or if this approach is viable at all. 字符迭代器的生存期应与StringStruct::system_string ,但是我不知道如何表达这种说法,或者这种方法是否可行。

To answer the question you asked, I'd recommend to impl IntoIterator for &StringStruct (a reference to a StringStruct instead of the struct directly). 要回答你问的问题,我建议你到impl IntoIterator for &StringStruct (一个参考 StringStruct ,而不是直接的结构)。 The code would look like this: 代码如下所示:

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

However, you will notice many more errors that have a different origin afterwards. 但是,之后您会注意到更多错误 ,这些错误的起源不同。 The next error that pops up is that Fn(char) -> u32 does not have a constant size at compile time. 弹出的下一个错误是Fn(char) -> u32在编译时大小没有恒定。

The problem is that you try to name the type of your closure by writing Fn(char) -> u32 . 问题是您尝试通过编写Fn(char) -> u32来命名闭包的类型。 But this is not the type of your closure, but merely a trait which is implemented by the closure. 但这不是关闭的类型,而仅仅是关闭所实现的特征。 The type of a closure can't be named (sometimes called "Voldemort type"). 闭包的类型无法命名 (有时称为“ Voldemort类型”)。

This means that, right now, you can't specify the type of a Map<_, _> object. 这意味着,现在您不能指定Map<_, _>对象的类型。 This is a known issue; 这是一个已知的问题; the recently accepted impl Trait -RFC might offer a workaround for cases like this. 最近接受的impl Trait -RFC可能为这种情况提供一种解决方法。 But right now, it's not possible, sorry. 但是现在,不可能,抱歉。

So how to solve it then? 那么如何解决呢? You need to create your own type that implements Iterator and use it instead of Map<_, _> . 您需要创建自己的实现Iterator的类型,并使用它代替Map<_, _> Note that you can still use the Chars iterator. 请注意,您仍然可以使用Chars迭代器。 Here is the full solution: 这是完整的解决方案:

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

And just a small note : an explicit return when not necessary is considered bad style in Rust. 请注意 :在Rust中,不必要时显式return是不好的样式。 Better stick to rule and write idiomatic code by removing return whenever possible ;-) 通过尽可能地消除return更好地遵守规则并编写惯用代码;-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM