flat_map на Chars вызывает ошибку проверки заимствования
Я пытаюсь создать последовательность, как это: 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());
^~~~~~~~~~~~~~~~~~~~~
Как я могу решить эту ошибку компилятора?
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);
}
}
Одна проблема с решением, которое использует 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<_>>()
);
}