Cell e RefCell
Cell e RefCell implementam o que Rust chama de mutabilidade interior: mutação de valores em um contexto imutåvel.
Cell Ă© normalmente usado para tipos simples, pois requer copiar ou mover valores. Tipos interiores mais complexos normalmente usam RefCell, que rastreia referĂȘncias compartilhadas e exclusivas em tempo de execução e retorna um pĂąnico (panic) se forem mal utilizadas.
use std::cell::RefCell; use std::rc::Rc; #[derive(Debug, Default)] struct Node { value: i64, children: Vec<Rc<RefCell<Node>>>, } impl Node { fn new(value: i64) -> Rc<RefCell<Node>> { Rc::new(RefCell::new(Node { value, ..Node::default() })) } fn sum(&self) -> i64 { self.value + self.children.iter().map(|c| c.borrow().sum()).sum::<i64>() } } fn main() { let root = Node::new(1); root.borrow_mut().children.push(Node::new(5)); let subtree = Node::new(10); subtree.borrow_mut().children.push(Node::new(11)); subtree.borrow_mut().children.push(Node::new(12)); root.borrow_mut().children.push(subtree); println!("graph: {root:#?}"); println!("graph sum: {}", root.borrow().sum()); }
- Se estivéssemos usando
Cellem vez deRefCellneste exemplo, terĂamos que mover oNodepara fora doRcpara enviar os filhos e, em seguida, movĂȘ-lo de volta. Isso Ă© seguro porque sempre hĂĄ um, valor nĂŁo referenciado emcell, mas nĂŁo Ă© ergonĂŽmico. - Para fazer qualquer coisa com um Node, vocĂȘ deve chamar um mĂ©todo
RefCell, geralmenteborrowouborrow_mut. - Demonstre que loops de referĂȘncia podem ser criados adicionando
rootasubtree.children(não tente imprimi-lo!). - Para demonstrar um pùnico em tempo de execução, adicione um
fn inc(&mut self)que incrementaself.valuee chama o mesmo mĂ©todo em seus filhos. Isso criarĂĄ um pĂąnico na presença do loop de referĂȘncia, comthread 'main' em pĂąnico no 'jĂĄ emprestado: BorrowMutError'.