Recall the following memory issue
char* str = "hello world";
char* sub = *str[5]
free(str);
printf("%s",sub);
Similar in Rust
let x = String::from ("Hello World");
let y = &x[6..10];
drop(x);
println!("{}",y);
Rust will not compile this
Slices reference a part of a continuous piece of memeory
let x = String::from ("Hello World");
let hello = &x[0..5];
let world = &x[6..11];
x: String
ptr -> Hello World
len: 11
capacity: 11
hello: &str
ptr -> x.ptr
len: 5
world: &str
ptr -> x.ptr[6]
len: 5
If x is dropped, so is everything else
x cannot be modifed while slices exist
Slices reference a part of a continuous piece of memeory
let a = [1,2,3,4];
let v = Vec::new();;
v.push(1);
let b = &a[1..3]
let w = &v[..2]
Arrays and vectors also have slices
struct User {
username: String,
active: bool,
}
let user1 = User {
username: String::from("clyff"),
active: true,
}
println!("{}",user1.username);
Mutability describes a variable, not the data
let mut x = User { ... };
x.active = false;
struct User {
username: String,
active: bool,
}
let user1 = User {
username: String::from("clyff"),
active: true,
}
println!("{}",user1.username);
Structs have associated functions
struct User {
username: String,
active: bool,
}
impl User{
fn is_online(&self){
self.active
}
}
Enums also are helpful for custom data types
enum Color{
Green,
Red,
Blue,
Other(String)
}
let r = Color::Red;
let o = Color::Other(String::from("Grey"));
Enums also have associated functions
impl Color{
fn is_green(&self)->bool{
match self{
Color::green => true,
_ => false,
}
}
}
Both Enums and Structs allow for Generics
struct Point<T>{
x:T,
y:T,
}
enum option<T>{
None,
Some(T),
}
Same for associated Functions
impl<T > Point<T>{
fn x(&self) -> &T{
&self.x
}
}
Hashmaps are built into Rust
let x = HashMap<i32,String>::new();
Like an Java intrerface
pub trait Printable{
fn print(&self) -> String;
}
impl Printable for User{
fn print(&self){
format!("{}:{}",self.username,self.active)
}
}
impl Printable for Point{
fn print(&self){
format!("({},{})",self.x,self.y)
}
}
default implemention: so also like abstract class
pub trait Printable{
fn print(&self) -> String{
"I was supposed to have this overridden"
}
}
Can have multiple and on a generic
struct Point<T:Clone + PartialOrd>{
x:T,
y:T,
}
Common Traits
Lifetimes are an implicit generic
Lifetime: scope for which a reference is valid
let r;
{
let x = 5;
r = &x;
}
println!("r: {}", r);
r and x have different lifetimes
Lifetimes are an implicit generic
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
x
} else {
y
}
}
Return type has no gaurantee it's a valid reference
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
struct ImportantString<'a>{
istring: &'a str,
}
The instance of ImportantString cannot outlive the reference it holds
let x = String::from("Hello world");
{
let y = ImportantString {istring:&x };
}
enum Tree{
Leaf,
Node(i32,Tree,Tree),
}
Issue: compiler does not know the size of Tree
enum Tree{
Leaf,
Node(i32,Box<Tree>,Box<Tree>),
}
References are pointers
let x = 5;
let y = &x;
assert_eq!(5, x);
assert_eq!(5, *y);
assert_eq!(5, y); //error here
Why do we not need to unpack the Box first?
let x = 5;
let y = Box::new(&x);
assert_eq!(5, x);
assert_eq!(5, *y);
Box has Deref and Drop traits
We can use this for functions
fn f(x: &str){
println!("echoing {x}")
}
let a = Box::new(String::from("echo..."));
f(&a);
Use DerefMut for mutability
(Cannot go from immut to mut)
Sometimes Box is not sufficient
let a = Node(3, Box::new(Box::new(Nil)),Box::new(Nil));
let b = Node(2, Box::new(Box::new(Nil)),Box::new(Nil));
let c = Node(1, Box::new(a),Box::new(b));
let d = Node(4, Box::new(a),Box::new(a)); //not ok
We can fix with RC (Reference counting)
We can fix with RC (Reference counting)
Allows for multiple owners with trade off of potential memory leaks
enum Tree{
Node(i32,Rc<Tree>,Rc<Tree>),
Nil
}
let a = Tree(3, Rc::new(Rc::new(Nil)),Rc::new(Nil));
let b = Tree(2, Rc::new(Rc::new(Nil)),Rc::new(Nil));
let c = Tree(1, Rc::clone(&a),Rc::clone(&b));
let d = Cons(4, Rc::clone(&a),Rc::clone(&a)); //now ok
Has all tradeoffs of RC
(like cyclic structures)