rust - Situations where Cell or RefCell is the best choice -


when required use cell or refcell? seems there many other type choices suitable in place of these, , documentation warns using refcell bit of "last resort".

is using these types "code smell"? can show example using these types makes more sense using type, such rc or box?

it not entirely correct ask when cell or refcell should used on box , rc because these types solve different problems. indeed, more not refcell used together rc in order provide mutability shared ownership. yes, use cases cell , refcell entirely dependent on mutability requirements in code.

interior , exterior mutability nicely explained in official rust book, in designated chapter on mutability. external mutability closely tied ownership model, , when mutable or immutable mean external mutability. name external mutability inherited mutability, explains concept more clearly: kind of mutability defined owner of data , inherited can reach owner. example, if variable of structural type mutable, fields of structure in variable:

struct point { x: u32, y: u32 }  // variable mutable... let mut p = point { x: 10, y: 20 }; // ...and fields reachable through variable p.x = 11; p.y = 22;  let q = point { x: 10, y: 20 }; q.x = 33;  // compilation error 

inherited mutability defines kinds of references can value:

{     let px: &u32 = &p.x;  // okay } {     let py: &mut u32 = &mut p.x;  // okay, because p mut } {     let qx: &u32 = &q.x;  // okay } {     let qy: &mut u32 = &mut q.y;  // compilation error since q not mut } 

sometimes, however, inherited mutability not enough. canonical example reference-counted pointer, called rc in rust. following code entirely valid:

{     let x1: rc<u32> = rc::new(1);     let x2: rc<u32> = x1.clone();  // create reference same data     let x3: rc<u32> = x2.clone();  // }  // here references destroyed , memory pointing @ deallocated 

at first glance not clear how mutability related this, recall reference-counted pointers called because contain internal reference counter modified when reference duplicated (clone() in rust) , destroyed (goes out of scope in rust). hence rc has modify though stored inside non-mut variable.

this achieved via internal mutability. there special types in standard library, basic of them being unsafecell, allow 1 work around rules of external mutability , mutate if stored (transitively) in non-mut variable.

another way has internal mutability can modified through &-reference - is, if have value of type &t , can modify state of t points at, t has internal mutability.

for example, cell can contain copy data , can mutated if stored in non-mut location:

let c: cell<u32> = cell::new(1); c.set(2); assert_eq!(c.get(), 2); 

refcell can contain non-copy data , can give &mut pointers contained value, , absence of aliasing checked @ runtime. explained in detail on documentation pages.


as turned out, in overwhelming number of situations can go external mutability only. of existing high-level code in rust written way. sometimes, however, internal mutability unavoidable or makes code clearer. 1 example, rc implementation, described above. 1 when need shared mutable ownership (that is, need access , modify same value different parts of code) - achieved via rc<refcell<t>>, because can't done references alone. example arc<mutex<t>>, mutex being type internal mutability safe use across threads.

so, can see, cell , refcell not replacements rc or box; solve task of providing mutability somewhere not allowed default. can write code without using them @ all; , if situation when need them, know it.

cells , refcells not code smell; reason whey described "last resort" move task of checking mutability , aliasing rules compiler runtime code, in case refcell: can't have 2 &muts pointing same data @ same time, statically enforced compiler, refcells can ask same refcell give &muts - except if more once panic @ you, enforcing aliasing rules @ runtime. panics arguably worse compilation errors because can find errors causing them @ runtime rather @ compilation time. sometimes, however, static analyzer in compiler restrictive, , indeed need "work around" it.


Comments

Popular posts from this blog

c# - Validate object ID from GET to POST -

node.js - Custom Model Validator SailsJS -

php - Find a regex to take part of Email -