Theory and Design of PL (CS 538)
March 25, 2020
&T
&mut T
// Can't change ref or thing it's pointing at
let immut_ref_to_immut = &my_string;
// Can't change ref, can change thing it's pointing at
let immut_ref_to_mut = &mut my_string;
// Can change ref, can't change thing it's pointing at
let mut mut_ref_to_immut = &my_string;
mut_ref_to_immut = &my_other_string;
// Can change ref and thing it's pointing at
let mut mut_ref_to_mut = &mut my_string;
mut_ref_to_mut = &mut my_other_string;
*mut_ref_to_mut = String::from("???");
One or the other: not both!
let mut mut_str = String::from("foo");
let mut_ref = &mut mut_str;
mut_ref.push("bar"); // OK
mut_str.push("baz"); // Not OK: can't access mut_str
// because mut_ref in scope
// Use scopes!
let mut mut_str_2 = String::from("foo");
{
let mut_ref_2 = &mut mut_str_2;
mut_ref_2.push("bar"); // OK
} // scope ends, mut_ref_2 gone
mut_str_2.push("baz"); // Now OK: no more mut_ref_2
Can’t mix shared and unique!
struct Triple(i32, i32, i32);
enum MyEnum {
Small(i32),
Big(Triple),
}
let mut my_enum = Big(Triple(1, 2, 3));
let mut im_ref: &i32 = &0; // points at 0
if let Big(b) = my_enum {
im_ref = &b.2; // points at last field in Big: 3
}
let m_ref = &mut my_enum; // mutable ref (not allowed)
*m_ref = Small(42); // change Big to Small
println!("Uh oh: {}", im_ref); // what does this point to?
fn take_mut_own(s: mut String) { s = String::from("wow"); }
// Pretty much the same as:
fn take_own(s: String) {
let mut owned_string = s;
owned_string = String::from("amazing");
}
fn main() {
let my_string = String::from("Hello!"); // Isn't mutable...
take_mut_own(my_string); // ... but this works?
println!("Still there? {}", my_string); // Not OK: it's gone!
}
let my_str = String::from("Hello world!");
let maybe_str = Some(my_str);
match maybe_str {
None => println!("Nothing!"),
Some(s) => println!("Something!"),
}
println!("Still there? {}", maybe_str.is_none());
Option<T>
let my_str = String::from("Hello world!");
let maybe_str = Some(my_str);
match maybe_str {
None => println!("Nothing!"),
Some(s) => println!("Something!"), // String *moved* into s
// s dropped here
}
println!("Still there? {}", maybe_str.is_none()); // Not OK!
maybe_str
is dropped: inner s
is gone!let my_str = String::from("Hello world!");
let maybe_str = Some(my_str);
let maybe_ref = &maybe_str;
match maybe_ref {
None => println!("Nothing!"),
Some(s) => println!("Something: {}", s), // what is type of s?
}
println!("Still there? {}", maybe_str.is_none());
&T
type: arms borrow immutably&mut T
type: arms borrow mutablylet my_str = String::from("Hello world!");
let maybe_str = Some(my_str);
let maybe_ref = &maybe_str; // immutable ref
match maybe_ref { // match on *immutable* ref
None => println!("Nothing!"),
Some(s) => println!("Something: {}", s), // can't mutate s
}
println!("Still there? {}", maybe_str.is_none());
let my_str = String::from("Hello world!");
let mut maybe_str = Some(my_str);
let maybe_ref = &mut maybe_str; // mutable ref
match maybe_ref { // match on *mutable* ref
None => println!("Nothing!"),
Some(s) => *s = String::from("Good bye!"), // mutate s
}
println!("What's here? {}", maybe_str.unwrap());
let my_str = String::from("Hello world!");
let mut maybe_str = Some(my_str);
match &maybe_str { // force immutable borrow
None => println!("Nothing!"),
Some(s) => println!("Something: {}", s), // can't mutate s
}
match &mut maybe_str { // force mutable borrow
None => println!("Nothing!"),
Some(s) => *s = String::from("Good bye!"), // mutate s
}
let my_str = String::from("Hello world!");
let mut maybe_str = Some(my_str);
match maybe_str { // force immutable borrow
None => println!("Nothing!"),
Some(ref s) => println!("Something: {}", s), // can't mutate s
}
match maybe_str { // force mutable borrow
None => println!("Nothing!"),
Some(ref mut s) => *s = String::from("Good bye!"), // mutate s
}