Я хочу написать универсальную функцию, которая берет любой неизменяемый итерируемый контейнер, такой как массив, Vec
, BTreeSet
и т.д. Так как эта функция является частью черты, которую я реализую, я не могу измените его подписи, поэтому невозможно сразу взять итератор в качестве параметра, и я также не могу представить какие-либо параметры времени жизни для сигнатуры функции.
Контекст
Я попытался реализовать шаблон наблюдателя в Rust. Наблюдаемый и наблюдатель выглядят следующим образом:
struct Observable<T> {
value: T,
}
impl<T> Observable<T> {
pub fn get(&self) -> &T {
&self.value
}
}
trait Observer<T> {
fn update(&self, &Observable<T>);
}
(Некоторые функции, не относящиеся к моей проблеме, опущены)
Теперь моя задача - написать наблюдателя, который можно использовать с произвольными итерационными контейнерами, в которых хранятся элементы, которым может быть присвоено значение. Он должен отслеживать сумму значений элементов в контейнере и, следовательно, удерживает текущую сумму и функцию, которая вычисляет значение любого элемента. Он должен реализовать признак Observer
, чтобы сумма могла обновляться каждый раз, когда контейнер изменяется.
struct SumObserver<T> {
current_sum: RefCell<i64>,
get_value: Fn(&T) -> i64,
}
Подходы до сих пор
Я безуспешно пытался получить функцию update
для компиляции в течение некоторого времени. Ниже приведена одна из версий функции, которую я пробовал:
impl<'a, T, L> Observer<L> for SumObserver<T>
where &'a L: IntoIterator<Item = &'a T>
{
fn update(&self, observable: &Observable<L>) {
let mut sum: i64 = 0;
for item in observable.get() {
sum += (self.get_value)(item);
}
*self.current_sum.borrow_mut() = sum;
}
}
Однако компилятор жалуется, что оба типа параметров T
и L
могут не прожить достаточно долго (E309). Сообщение об ошибке даже остается неизменным, если весь элемент функции закомментирован. Если я также удаляю where-clause, компиляция работает.
Если я следую предложению компиляторов для добавления явных ограничений срока службы к типам параметров, компилятор выдаст следующий результат:
src/main.rs:25:26: 25:29 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495]
src/main.rs:25 for item in observable.get() {
^~~
Затем он предлагает добавить явный параметр lifetime к параметру observable
, который невозможен, поскольку он изменит сигнатуру функции, которая требуется для этого признака.
Я не понимаю проблему с временами жизни в этой функции. В любой момент, когда эта функция вызывается, компилятор должен убедиться, что заем observable
длится, по крайней мере, до тех пор, пока функция не вернется. В то время любой заем observable
вышел из сферы действия.