【问题标题】:flat_map on Chars causes borrow checker errorChars 上的 flat_map 导致借用检查器错误
【发布时间】:2016-09-04 14:41:37
【问题描述】:

我正在尝试生成这样的序列:1,2,3,4,5,6,7,8,9,1,0,1,1,1,2...

fn main() {
    let iter = (1..).flat_map(|j| j.to_string().chars());
    for i in iter {
        println!("{}", i);
    }
}

这不起作用,因为j.to_string() 超出了我认为的范围(但为什么?)

p040.rs:2:35: 2:48 error: borrowed value does not live long enough
p040.rs:2     let iter = (1..).flat_map(|j| j.to_string().chars());
                                            ^~~~~~~~~~~~~
p040.rs:2:58: 6:2 note: reference must be valid for the block suffix following statement 0 at 2:57...
p040.rs:2     let iter = (1..).flat_map(|j| j.to_string().chars());
p040.rs:3     for i in iter {
p040.rs:4         println!("{}", i);
p040.rs:5     }
p040.rs:6 }
p040.rs:2:35: 2:56 note: ...but borrowed value is only valid for the block at 2:34
p040.rs:2     let iter = (1..).flat_map(|j| j.to_string().chars());
                                            ^~~~~~~~~~~~~~~~~~~~~

我该如何解决这个编译器错误?

【问题讨论】:

  • 在 C++ 程序中引用像这样的临时文件是我发现的最常见的错误之一。它通常持续足够长的时间以通过测试,直到编译器更新或有人将新变量添加到本地范围。很高兴它为你抓住了这个。

标签: iterator rust flatmap


【解决方案1】:

迭代器是懒惰的,只能与迭代器的生命一样长。 j.to_string() 是临时的,只存在于闭包内,因此闭包不能返回j.to_string().chars()。 一个简单的解决方案是在返回之前收集字符:

fn main() {
    let iter = (1..).flat_map(|j| j.to_string().chars().collect::<Vec<_>>());
    for i in iter {
        println!("{}", i);
    }
}

【讨论】:

    【解决方案2】:

    使用collect 的解决方案的一个问题是它不断分配字符串和向量。如果您需要一个实现最小分配的实现,您可以实现自己的迭代器:

    #[derive(Default)]
    struct NumChars {
        num: usize,
        num_str: Vec<u8>,
        next_index: usize,
    }
    
    impl Iterator for NumChars {
        type Item = char;
    
        fn next(&mut self) -> Option<char> {
            use std::io::Write;
            if self.next_index >= self.num_str.len() {
                self.next_index = 0;
                self.num += 1;
                self.num_str.clear();
                write!(&mut self.num_str, "{}", self.num).expect("write failed");
            }
    
            let index = self.next_index;
            self.next_index += 1;
            Some(self.num_str[index] as char)
        }
    }
    
    fn main() {
        assert_eq!(
            vec!['1', '2', '3', '4', '5', '6', '7', '8', '9', '1', '0', '1', '1'],
            NumChars::default().take(13).collect::<Vec<_>>()
        );
    }
    

    【讨论】:

    • 我的方法是绕过错误的简单方法,但在现实生活中会更好。
    猜你喜欢
    • 2016-09-20
    • 2022-11-11
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多