Я хочу построить рекурсивную функцию для обхода дерева в Rust. Функция всегда должна получать следующий элемент и итератор по ссылкам на элементы-предки.
Для итератора по элементам-предкам в принципе можно использовать методы chain
и once
. Рассмотрим следующий простой пример, где дерево - это Ve c (для целей этой демонстрации):
fn proceed<'a, I>(mut remaining: Vec<String>, ancestors: I)
where
I: Iterator<Item = &'a String> + Clone,
{
if let Some(next) = remaining.pop() {
let next_ancestors = ancestors.chain(std::iter::once(&next));
proceed(remaining, next_ancestors);
}
}
Детская площадка
Это не удается компилировать, потому что &next
имеет более короткое время жизни, чем 'a
:
error[E0597]: `next` does not live long enough
--> src/lib.rs:6:62
|
1 | fn proceed<'a, I>(mut remaining: Vec<String>, ancestors: I)
| -- lifetime `'a` defined here
...
6 | let next_ancestors = ancestors.chain(std::iter::once(&next));
| --------------------------------^^^^^--
| | |
| | borrowed value does not live long enough
| argument requires that `next` is borrowed for `'a`
7 | proceed(remaining, next_ancestors);
8 | }
| - `next` dropped here while still borrowed
Я попытался преодолеть это путем добавления явного второго времени жизни 'b: 'a
и принудительного использования явной ссылки чем-то вроде let next_ref: &'b String = &next
, но это также приводит к (другому) сообщению об ошибке.
Одно из решений, которое я придумала, это вызвать map
следующим образом:
let next_ancestors = ancestors.map(|r| r).chain(std::iter::once(&next));
Как указано @trentcl, это на самом деле не решает проблему , поскольку компилятор застревает в бесконечном l oop при компиляции proceed
для всех вложенных Chain
s, когда кто-то пытается вызвать функцию.