Сегодня - о замечательной функции
Cell::from_mutОна позволяет превратить
&mut T в &Cell<T>, что все еще позволяет изменять T, но ее разрешается расшаритьВот классический пример, где как новичики, так и ветераны спотыкаются о borrow checker
let mut counter = 0;
let mut inc = || counter += 1;
let print = || println!("{}", counter); // cannot borrow `counter` as immutable because it is also borrowed as mutable
inc();
inc();
print();
❌ Передать
&mut в inc и одновременно & в print нельзя. ❌Здесь мы можем использовать магию
Cell::from_mut, не изменяя окружающий код.Обернем ссылку на
counter и раздадим в замыкания.
let mut counter = 0;
let cell = Cell::from_mut(&mut counter);
let inc = || cell.set(cell.get() + 1);
let print = || println!("{}", cell.get());
inc();
inc();
print();
🎉 И вуаля - всё работает! 🎉
Бонус для внимательных:
Теперь
inc теперь реализует и Fn.Так что можно тот же трюк использовать что бы передать замыкание, которое что-то мутирует в функцию, которая принимает
Fn без Send.