Advance Rust APIs
Collections
Rust’s standard library includes a number of very useful data structures called collections.
Most other data types represent one speci c value, but collections can contain multiple values.
the data these collections point to is stored on the heap
fi
Vectors
Vectors
Vectors allow you to store more than one
value in a single data structure that puts all
the values next to each other in memory.
Vectors
Q: Write a function that takes a vector
as an input and returns a vector with
even values
Vectors
Q: Write a function that takes a vector
as an input and returns a vector with
even values
Approach #1
Vectors
Q: Write a function that takes a vector
as an input and returns a vector with
even values
Approach #2
Vectors
Initialising using rust macros
Vectors
De ning the type of the vector as a
generic
fi
Vectors
Explicitly giving type using generics
Hashmaps
Hashmaps
Hashmaps stores a key value pair in rust.
Similar to objects in JS
Dict in Python
HashMaps in Java
Hashmaps
Methods -
1. insert
2. get
3. remove
4. clear
Hashmap
Q: Write a function that takes a vector of tuples (each tuple containing a key and a
value) and returns a Hashmap where the keys are the unique keys from the input tuples
and the values are vectors of all corresponding values associated with each key.
Hashmap
Q: Write a function that takes a vector of tuples (each tuple containing a key and a
value) and returns a Hashmap where the keys are the unique keys from the input tuples
and the values are vectors of all corresponding values associated with each key.
Iterators
Iterators
1. Iterating using for loops
Iterators
2. Iterating after creating an `iterator`
Iterators
2. Iterating after creating an `iterator`
The iter() method in Rust
provides a way to iterate
over the elements of a
collection by borrowing
them.
You can’t mutate the
variables since we have an
immutable reference to the
internal elements
Iterators
3. Iterating using `.next`
Iterators
3. Iterating using `.next`
You can’t mutate the data
here either
The `iterator` is mutable,
but the inner elements (val)
still is an immutable
reference
Iterators
4. IterMut
Iterators
5. IntoIter
Iterators
5. IntoIter
The IntoIterator trait is used to
convert a collection into an
iterator that takes ownership of
the collection.
Useful when
1. You no longer need the
original collection
2. When you need to squeeze
performance bene ts by
transferring ownership
(avoiding references)
fi
Iterators
5. IntoIter
The for syntax when applied directly on the collection uses into_iter under the hood
same
Iterators
Which to chose?
Iter IterMut IterInto
If you want immutable
If you want mutable If you want to move the
references to the inner
references to the inner variable into the iterator
variables and don’t want
variables and don’t want and don’t want to use it
to transfer ownership
to transfer ownership afterwards
Iterators
Consuming adapters
Methods that call next are called consuming adaptors, because calling them uses up the iterator.
v1_iter can’t be used again
Iterators
Iterator adaptors are methods de ned on the Iterator trait that don’t consume the
iterator. Instead, they produce di erent iterators by changing some aspect of the
original iterator.
ff
fi
Iterators
Iterator adaptors are methods de ned on the Iterator trait that don’t consume the
iterator. Instead, they produce di erent iterators by changing some aspect of the
original iterator.
1. map ff
fi
Iterators
Iterator adaptors are methods de ned on the Iterator trait that don’t consume the
iterator. Instead, they produce di erent iterators by changing some aspect of the
original iterator.
1. map
2. lter
fi
ff
fi
Iterators
Assignment -
Write the logic to rst lter all odd values then double each value and create a new
vector
fi
fi
Iterators
Assignment -
Write the logic to rst lter all odd values then double each value and create a new
vector
fi
fi
Iterators
Assignment -
Write the logic to rst lter all odd values then double each value and create a new
vector
fi
fi
Iterators in Hashmaps
Strings vs slices
Strings
1. Creating a string
Strings
1. Creating a string
2. Mutating a string
Strings
1. Creating a string
2. Mutating a string
3. Deleting from a string
Strings
Slices
Slices
Lets understand why we need slices
With a common example (from the rust book) of how it provides memory safety
Slices
Q: Write a function that takes a string as an input
fi
And returns the rst word from it
Slices
Q: Write a function that takes a string as an input
And returns the rst word from it
Approach #1 - Return a new string
fi
Slices
Q: Write a function that takes a string as an input
And returns the rst word from it
Approach #1 - Return a new string
Problem -
1. We take up double the memory
2. If the `name` string gets `cleared` ,
`ans` still has `hello` as the value in it
fi
Slices
Q: Write a function that takes a string as an input
And returns the rst word from it
Approach #1 - Return a new string
Problem -
1. We take up double the memory
2. If the `name` string gets `cleared` ,
`ans` still has `hello` as the value in it
What we want is a `view` into the original string
And not copy it over
fi
Slices
Q: Write a function that takes a string as an input
And returns the rst word from it
Name
Approach #1 - Return a new string
Problem -
1. We take up double the memory
2. If the `name` string gets `cleared` ,
`ans` still has `hello` as the value in it
Ans
What we want is a `view` into the original string
And not copy it over
fi
Slices
Q: Write a function that takes a string as an input
Approach #1 (with slices) And returns the rst word from it
Ans
fi
Slices
Q: Write a function that takes a string as an input
And returns the rst word from it
Approach #2 (with slices)
Ans
fi
Slices
Q: Write a function that takes a string as an input
And returns the rst word from it
Approach #2 (with slices) (alt)
Name
Ans
fi
Slices
3 types of commonly used strings (there are actually much more)
Slices
Slices can also be applied to other collections like vectors/arrays
Generics
From the live meet-up
Impl blocks
From the live meet-up
Traits
Traits
Traits
De ning the trait
fi
Traits
De ning a struct
fi
Traits
Implementing a
Trait on the struct
Traits
De ning the struct
and using its function
fi
Traits
Default implementations
Traits
Default implementations
De ning the
`default implementation`
fi
Traits
Default implementations
Doesn’t error out
Traits
Traits as parameters
Traits
Traits as parameters
Trait as an argument
Traits
Traits as parameters
Can call summarise on it
Traits
Trait bound syntax
Traits
Trait bound syntax
Traits
Trait bound syntax
The generic is bound to the trait
Traits
Multiple Trait bounds
Multiple trait bounds
Lifetimes
Lifetimes are hard to digest.
Takes a lot of time to understand why they are needed
Lot of times the compiler will help you and guide you in the right direction
Lifetimes
Goal is by the end of this section
You can understand the following syntax
Lifetimes
Q - Write a function that takes two strings as an input
And returns the bigger amongst them
Lifetimes
Q - Write a function that takes two strings as an input
And returns the bigger amongst them
Lifetimes
Q - Write a function that takes two
strings as an input
And returns the bigger amongst them
Lifetimes
Q - Write a function that takes two
strings as an input
And returns the bigger amongst them
longest_str is de ned
fi
Lifetimes
Q - Write a function that takes two
strings as an input
And returns the bigger amongst them
str1 is de ned
fi
Lifetimes
Q - Write a function that takes two
strings as an input
And returns the bigger amongst them
Str2 is de ned
fi
Lifetimes
Q - Write a function that takes two
strings as an input
And returns the bigger amongst them
str1 and str2 both get moved
Lifetimes
Q - Write a function that takes two
strings as an input Check
And returns the bigger amongst them
Lifetimes
Q - Write a function that takes two
strings as an input
And returns the bigger amongst them
str2 moves to longest_str
Lifetimes
Q - Write a function that takes two
strings as an input
And returns the bigger amongst them
longest_str is valid
Lifetimes
Now lets change the syntax a bit
Lifetimes
Do you think this is valid syntax?
Lifetimes
Do you think this is valid syntax?
Yes
Lifetimes
str1 owns the string
Lifetimes
str2 owns the string
Lifetimes
Both str1 and str2 get moved
Lifetimes
B (str1) gets moved back
Lifetimes
B (str1) gets moved back
Lifetimes
longest_str owns the string
Lifetimes
longest_str owns gets printed
Lifetimes
What we’ve done until now has nothing to do with lifetimes
Lifetimes
What we’ve done until now has nothing to do with lifetimes
Lets change the function signature a bit
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Do you think this code is valid?
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Do you think this code is valid?
No
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Can you look at the code and tell
Why the compiler complaining is a good thing?
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Points to nothing
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Str1 owns the string
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Str2 owns the string
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Str1 and str2 get borrowed
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Condition checks
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
Reference to b gets returned
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
longest_string is a string slice
Pointing to str2
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
longest_string is a string slice
Pointing to str2
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
str2 goes out of scope
Data gets removed from the heap
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
longest_str is a dangling pointer
Lifetimes
Q - Write a function that takes two string references as an input
And returns the bigger amongst them
How to x the error?
fi
Lifetimes
How to x the error? - Specify lifetimes
fi
Lifetimes
How to x the error? - Specify lifetimes
Very similar to a generic
Called a generic lifetime annotation
fi
Lifetimes
How to x the error? - Specify lifetimes
Very similar to a generic
Called a generic lifetime parameter
fi
Lifetimes
How to x the error? - Specify lifetimes
Describe a relationship
b/w the lifetimes of input args
and output args
fi
Lifetimes
How to x the error? - Specify lifetimes
Describe a relationship
b/w the lifetimes of input args
and output args
It says that the `return type`
will be valid as long as both
the arguments are valid
fi
Lifetimes
How to x the error? - Specify lifetimes
Describe a relationship
b/w the lifetimes of input args
and output args
It says that the `return type`
will be valid as long as both
the arguments are valid
Or more technically, the shorter lifetimes is what the return type will have
fi
Lifetimes
Lifetimes
Now if you run this code,
it fails with a better error
Lifetimes
Now if you run this code, Live long enough = lifetime of return value ends
it fails with a better error
Structs with lifetimes
Until now, we haven’t used references inside a struct
Lets try that
Structs with lifetimes
Until now, we haven’t used references inside a struct
Lets try that
Structs with lifetimes
Until now, we haven’t used references inside a struct
Lets try that
Structs with lifetimes
Until now, we haven’t used references inside a struct
Lets try that
Structs with lifetimes
Why do you need structs with references to have a lifetime parameter?
Structs with lifetimes
Why do you need structs with references to have a lifetime parameter?
So we know how long the `struct` can live
Structs with lifetimes
Structs with lifetimes
This code doesn’t compile
Because
Structs with lifetimes
This code doesn’t compile
Because
last_name doesn’t live long enough
Structs with lifetimes
Checkpoint
✅
✅
✅
✅
✅
✅
✅
Multithreading
Multithreading
Core 1 Core 2 Core 3 Core 4 Core 5
Core 6 Core 7 Core 8 Core 9 Core 10
Multithreading
Core 1 Core 2 Core 3 Core 4 Core5
Core 6 Core 7 Core 8 Core 9 Core 10
Multithreading
Main thread Spawned thread
Core 1 Core 2 Core 3 Core 4 Core5
Core 6 Core 7 Core 8 Core 9 Core 10
Multithreading
Multithreading
Awaiting the thread to nish
Before running the iteration on the main thread
fi
Multithreading
Multithreading
Multithreading
This code doesn’t compile
Because `v` could go out of scope before the thread starts
Multithreading
This code doesn’t compile
Because `v` could go out of scope before the thread starts
Multithreading
This code does compile
Because we `move` v to the spawned thread
It can not be used in the main thread anymore
Message passing
Pass a variable over
Thread 1 Thread 2
Core 1 Core 2 Core 3 Core 4 Core 5
Core 6 Core 7 Core 8 Core 9 Core 10
Message passing
Pass a variable over
Thread 1 Thread 2
Core 1 Core 2 Core 3 Core 4 Core 5
Core 6 Core 7 Core 8 Core 9 Core 10
Use case?
One thread reading data from redis ,
other thread processing it
Message passing
Pass a variable over
Thread 1 Thread 2
Core 1 Core 2 Core 3 Core 4 Core 5
Core 6 Core 7 Core 8 Core 9 Core 10
Use case?
One thread reading data from redis ,
other thread processing it
Message passing
Channels
Thread 1 Thread 2
Core 1 Core 2 Core 3 Core 4 Core 5
Core 6 Core 7 Core 8 Core 9 Core 10
Message passing
Channels
Message passing
Channels
Can you write the code that nds the sum from 1 - 10^8?
fi
Message passing
Channels
Can you write the code that nds the sum from 1 - 10^8?
Use threads to make sure you use all cores of your machine
fi
Message passing
Channels
Can you write the code that nds the sum from 1 - 10^8?
Use threads to make sure you use all cores of your machine
Remember the name says `multiple producer single consumer`
fi
Message passing
Hint -
You can clone a producer before moving it to a thread
Message passing
Channels
Can you write the code that nds the sum from 1 - 10^8?
fi
Message passing
This code almost works
Message passing
This code almost works
Can you guess what goes wrong here?
Message passing
This code almost works
Can you guess what goes wrong here?
The original tx variable never
drops, and so the for loop
keeps on waiting for data from it
Message passing
This code almost works
Can you guess what goes wrong here?
Message passing
Right solution
Async rust