1

I'm trying to generate a sequence like this: 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);
    }
}

This does not work, because j.to_string() goes out of scope I believe (but why?)

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());
                                            ^~~~~~~~~~~~~~~~~~~~~

How could I solve this compiler error?

4

2 回答 2

2

迭代器是惰性的,并且只能与迭代器的生命一样长。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);
    }
}
于 2016-05-09T20:19:08.273 回答
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-05-10T17:40:49.977 回答