В вашем объявлении типа:
type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;
Вы говорите, что базовые фрагменты, которые вы используете для построения своих итераторов, должны иметь 'static
время жизни, то есть они должны жить вечно. Затем вы используете литеральные массивы, такие как [1, 2]
, которые, как и все литералы, имеют 'static'
время жизни и все идет хорошо:
let r: &'static [i32; 2] = &[1, 2]; //Ok
Но затем вы пытаетесь код, подобный этому более простому:
let a = [1, 2].map(|x| 2 * x);
let r: &'static [i32; 2] = &a; //error: borrowed value does not live long enough
В результате arraymap::map
является обычным массивом, а не литералом, поэтому у него нет времени жизни 'static
. Это не может быть stati c, потому что вы вычисляете значения во время выполнения. Он будет жить столько времени, сколько необходимо, в моем случае до тех пор, пока переменная a
.
В вашем случае, поскольку возвращаемые значения arraymap::map
не присваиваются переменным, они являются временными значениями и являются быстро упал. Но даже если вы присвоили его локальной переменной, вы не могли бы вернуть ссылку на нее, потому что локальная переменная удаляется после завершения функции.
Решение состоит в том, чтобы вернуть итератор, которому принадлежит значение. Примерно так работает:
type IntegerCycle = Cycle<std::vec::IntoIter<i32>>;
fn generate_cycles() -> [IntegerCycle; 2] {
let cycles = [
[1, 2],
[2, 4],
];
cycles
.map(|points| {
points.map(|point| point*2)
})
.map(|points| {
points.to_vec().into_iter().cycle()
})
}
К сожалению, вам нужно использовать Vec
вместо массива, потому что нет реализации IntoIterator
для массивов (есть для слайсов, но они не владеть значениями).
Если вы хотите избежать дополнительного выделения Vec
, вы можете использовать ящик arrayvec
, который позволяет переносить итератор в массив:
type IntegerCycle = Cycle<arrayvec::IntoIter<[i32; 2]>>;
fn generate_cycles() -> [IntegerCycle; 2] {
let cycles = [
[1, 2],
[2, 4],
];
cycles
.map(|points| {
points.map(|point| point*2)
})
.map(|points| {
let a = arrayvec::ArrayVec::from(*points);
a.into_iter().cycle()
})
}
ПРИМЕЧАНИЕ: Похоже, что есть попытка добавить правильный IntoIterator
impl для массивов со значением к std
, но все еще есть некоторые нерешенные проблемы.