Я пытаюсь написать функцию уменьшения в стиле продолжения, которую можно возобновить в любой момент.У меня есть работающая версия, но в этом я должен явно написать новую версию функции, если я хочу, чтобы она могла использовать заимствование некоторого состояния. Rust Playground Link
fn reduce_async_with_store<'a, I, A, F, C>(
store: &mut Store,
mut iterator: I,
accumulator: A,
mut f: F,
continuation: C,
) where
I: Iterator + 'a,
F: FnMut(&mut Store, I::Item, A, Box<dyn FnOnce(&mut Store, A) + 'a>) + Clone + 'a,
C: FnOnce(&mut Store, A) + 'a,
{
match iterator.next() {
None => continuation(store, accumulator),
Some(item) => {
let next: Box<dyn FnOnce(&mut Store, A) + 'a> = {
let f = f.clone();
Box::new(move |store, accumulator| {
reduce_async_with_store(store, iterator, accumulator, f, continuation)
})
};
f(store, item, accumulator, next);
}
}
}
fn some_operation(state: &mut Store, continuation: Box<dyn FnOnce(&mut Store) + 'static>) {
let mut new_state = Store { foo: state.foo };
continuation(&mut new_state);
}
#[derive(Debug)]
pub struct Store {
foo: u8,
}
fn main() {
let mut some_state = Store { foo: 0 };
let arr = vec![1u8, 2u8, 3u8];
reduce_async_with_store(
&mut some_state,
arr.into_iter(),
Vec::new(),
|store, item, mut acc, continuation| {
println!("Item: {}", item);
store.foo += item;
acc.push(item);
some_operation(
store,
Box::new(move |stor| {
continuation(stor, acc);
}),
);
},
|store, acc| {
println!("Done!! {:?} {:?}", store, acc);
},
)
}
Вот версия этой функции, которую я хотел бы написать, где я могу передать Store
как часть аккумулятора и вытащить его- однако, если я сделаю это, я получу cannot infer an appropriate lifetime due to conflicting requirements
.
Rust Playground Link
fn reduce_async<'a, I, A, F, C>(mut iterator: I, accumulator: A, mut f: F, continuation: C)
where
I: Iterator + 'a,
F: FnMut(I::Item, A, Box<dyn FnOnce(A) + 'a>) + Clone + 'a,
C: FnOnce(A) + 'a,
{
match iterator.next() {
None => continuation(accumulator),
Some(item) => {
let next: Box<dyn FnOnce(A) + 'a> = {
let f = f.clone();
Box::new(move |accumulator| reduce_async(iterator, accumulator, f, continuation))
};
f(item, accumulator, next);
}
}
}
fn some_operation(state: &mut Store, continuation: Box<dyn FnOnce(&mut Store) + 'static>) {
let mut new_state = Store { foo: state.foo };
continuation(&mut new_state);
}
#[derive(Debug)]
pub struct Store {
foo: u8,
}
fn main() {
let mut some_state = Store { foo: 0 };
let arr = vec![1u8, 2u8, 3u8];
reduce_async(
arr.into_iter(),
(&mut some_state, Vec::new()),
|item, mut acc, continuation| {
let (store, vec) = acc;
println!("Item: {}", item);
store.foo += item;
vec.push(item);
some_operation(
store,
Box::new(move |store| {
continuation((store, vec));
}),
);
},
|(store, vec)| {
println!("Done!! {:?} {:?}", store, vec);
},
)
}
Как я могу написать эту неспециализированную версию своей функциии передать такие вещи, как &mut Store
, соблюдая при этом времена жизни Rust?
Почему мой первый пример с reduce_async_with_store
разрешен, даже если я не указываю явное время жизни для &mut Store
, ион может существовать до тех пор, пока 'static
?
some_operation
не будет заключен в рамку, потому что это то, что принимает сторонняя API-функция, которую я вызываю.Я хотел бы в конечном итоге заменить этот код асинхронными итераторами, но библиотека, которую я использую, пока не поддерживает фьючерсы.