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
Cell
em vez deRefCell
neste exemplo, terĂamos que mover oNode
para fora doRc
para 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
, geralmenteborrow
ouborrow_mut
. - Demonstre que loops de referĂȘncia podem ser criados adicionando
root
asubtree.children
(não tente imprimi-lo!). - Para demonstrar um pùnico em tempo de execução, adicione um
fn inc(&mut self)
que incrementaself.value
e 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'
.