1
Hack without fear!
Nicholas Matsakis
2
Systems programming without the hassle
2
Systems programming without the hassle
crashes
heisenbugs
fear
2
Systems programming without the hassle
crashes
heisenbugs
fear
Parallel!
// sums all the positive values in `v`
fn sum_pos(v: &[i32]) -> i32 {
let mut sum = 0;
for i in v.iter().filter(|i| **i > 0) {
sum += *i;
}
sum
}
High-level coding
3
// sums all the positive values in `v`
fn sum_pos(v: &[i32]) -> i32 {
let mut sum = 0;
for i in v.iter().filter(|i| **i > 0) {
sum += *i;
}
sum
}
High-level coding
3
Iterators.
Closures.
Assembly code
4
leaq (%rdi,%rsi,4), %rcx
xorl %eax, %eax
jmp .LBB5_1
.LBB5_3:
addl %edx, %eax
.align 16, 0x90
.LBB5_1:
cmpq %rdi, %rcx
je .LBB5_4
movl (%rdi), %edx
addq $4, %rdi
testl %edx, %edx
jle .LBB5_1
jmp .LBB5_3
.LBB5_4:
retq
fn foo(v: &[i32]) -> i32 {
v.iter()
.filter(|i| **i > 0)
.map(|i| *i)
.sum()
}
Higher-level coding
5
…generates the same assembly code.
Safe
6
fn this_wont_compile(v: &mut Vec<i32>) -> i32 {
let mut sum = 0;
for &i in v.iter() {
sum += i;
if i > 0 { v.push(0); }
}
sum
}
Safe
6
fn this_wont_compile(v: &mut Vec<i32>) -> i32 {
let mut sum = 0;
for &i in v.iter() {
sum += i;
if i > 0 { v.push(0); }
}
sum
}
Might free
underlying buffer.
Safe
6
fn this_wont_compile(v: &mut Vec<i32>) -> i32 {
let mut sum = 0;
for &i in v.iter() {
sum += i;
if i > 0 { v.push(0); }
}
sum
}
error: cannot borrow `*v` as mutable because it is also borrowed
as immutable
if i > 0 { v.push(0); }
^
note: previous borrow of `*v` occurs here; the immutable borrow
prevents subsequent moves or mutable borrows of `*v` until
the borrow ends
for &i in v.iter() {
^
Might free
underlying buffer.
fn parallel_qsort(vec: &mut [int]) {
if vec.len() <= 1 { return; }
let pivot = vec[random(vec.len())];
let mid = vec.partition(vec, pivot);
let (less, greater) = vec.split_at_mut(mid);
rayon::join(
|| parallel_qsort(less),
|| parallel_qsort(greater)
);
}
Parallel
7Caveat: shameless plug for third-party package of mine.
fn parallel_qsort(vec: &mut [int]) {
if vec.len() <= 1 { return; }
let pivot = vec[random(vec.len())];
let mid = vec.partition(vec, pivot);
let (less, greater) = vec.split_at_mut(mid);
rayon::join(
|| parallel_qsort(less),
|| parallel_qsort(greater)
);
}
Parallel
7
Sort left and right
in parallel.Caveat: shameless plug for third-party package of mine.
fn parallel_qsort(vec: &mut [int]) {
if vec.len() <= 1 { return; }
let pivot = vec[random(vec.len())];
let mid = vec.partition(vec, pivot);
let (less, greater) = vec.split_at_mut(mid);
rayon::join(
|| parallel_qsort(less),
|| parallel_qsort(less)
);
}
Parallel… and safe
8
Data race.
fn parallel_qsort(vec: &mut [int]) {
if vec.len() <= 1 { return; }
let pivot = vec[random(vec.len())];
let mid = vec.partition(vec, pivot);
let (less, greater) = vec.split_at_mut(mid);
rayon::join(
|| parallel_qsort(less),
|| parallel_qsort(less)
);
}
Parallel… and safe
8
error: closure requires unique access to `less`
but it is already borrowed
|| parallel_qsort(less)
^~~~~~~~~~~~~~~~~~~~~~~
Data race.
Open and welcoming
Rust has been open source from the beginning.
!
Open governance model based on public RFCs.
!
We have an active, amazing community.
❤
9
The Plan
10
1. Hello, world!
2. Structs and such.
3. Threads.
11
Hello, world!
Hello, world!
12
smallcultfollowing.com/20151209/
!
Example “Hello World”
fn main() {
println!(“Hello, world!”);
}
Ownership!
!
n. The act, state, or right of possessing something.
13
Borrow!
!
v. To receive something with the promise of returning it.
Ownership/Borrowing
Memory
safety
Data-race
freedom
No need for
a runtime
14
Ownership/Borrowing
Memory
safety
Data-race
freedom
No need for
a runtime
C++
14
Ownership/Borrowing
Memory
safety
Data-race
freedom
No need for
a runtime
GCC++
14
Ownership
15
Ownership
15
fn main() {
let name = format!(“…”);
helper(name);
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Ownership 16
fn main() {
let name = format!(“…”);
helper(name);
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Ownership 16
fn main() {
let name = format!(“…”);
helper(name);
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Ownership
Take ownership
of a String
16
fn main() {
let name = format!(“…”);
helper(name);
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Ownership 16
fn main() {
let name = format!(“…”);
helper(name);
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Ownership 16
fn main() {
let name = format!(“…”);
helper(name);
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Ownership 16
fn main() {
let name = format!(“…”);
helper(name);
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Ownership 16
fn main() {
let name = format!(“…”);
helper(name);
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Ownership 16
fn main() {
let name = format!(“…”);
helper(name);
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Ownership 16
fn main() {
let name = format!(“…”);
helper(name);
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Ownership 16
Error: use of moved value: `name`
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java
Take reference
to Vector
17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
new Thread(…);
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
new Thread(…);
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
new Thread(…);
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
new Thread(…);
void main() {
Vector name = …;
helper(name);
helper(name);
}
void helper(Vector name) {
…
}
!
!
!
“Ownership” in Java 17
new Thread(…);
Clone
18
fn main() {
let name = format!(“…”);
helper(name.clone());
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Clone
18
fn main() {
let name = format!(“…”);
helper(name.clone());
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Clone
18
fn main() {
let name = format!(“…”);
helper(name.clone());
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Copy the String
Clone
18
fn main() {
let name = format!(“…”);
helper(name.clone());
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Clone
18
fn main() {
let name = format!(“…”);
helper(name.clone());
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Clone
18
fn main() {
let name = format!(“…”);
helper(name.clone());
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Clone
18
fn main() {
let name = format!(“…”);
helper(name.clone());
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Clone
18
fn main() {
let name = format!(“…”);
helper(name.clone());
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Clone
18
fn main() {
let name = format!(“…”);
helper(name.clone());
helper(name);
}
fn helper(name: String) {
println!(..);
}
!
!
!
Copy (auto-Clone)
19
fn main() {
let name = 22;
helper(name);
helper(name);
}
fn helper(name: i32) {
println!(..);
}
!
!
!
Copy (auto-Clone)
19
fn main() {
let name = 22;
helper(name);
helper(name);
}
fn helper(name: i32) {
println!(..);
}
!
!
!
i32 is a Copy type
Copy (auto-Clone)
19
fn main() {
let name = 22;
helper(name);
helper(name);
}
fn helper(name: i32) {
println!(..);
}
!
!
!
i32 is a Copy type
Copy (auto-Clone)
19
fn main() {
let name = 22;
helper(name);
helper(name);
}
fn helper(name: i32) {
println!(..);
}
!
!
!
i32 is a Copy type
Copy (auto-Clone)
19
fn main() {
let name = 22;
helper(name);
helper(name);
}
fn helper(name: i32) {
println!(..);
}
!
!
!
i32 is a Copy type
Copy (auto-Clone)
19
fn main() {
let name = 22;
helper(name);
helper(name);
}
fn helper(name: i32) {
println!(..);
}
!
!
!
i32 is a Copy type
20
Non-copyable: Values move from place to place.
Examples: File descriptor, database handle.
!
Clone: Run custom code to make a copy.
Examples: String, Vector!
!
Copy: Type is implicitly copied when referenced.
Examples: u32, i32, (f32, i32).
Exercise: ownership
21
http://smallcultfollowing.com/20151209
Cheat sheet:
fn helper(name: String) // takes ownership
!
string.clone() // clone the string
http://doc.rust-lang.org/std
Borrowing
22
Borrowing
22
Borrowing
22
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow 23
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow 23
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow 23
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow
Take a reference
to a String
23
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow
Take a reference
to a String
23
Lend the string
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow
Take a reference
to a String
23
Lend the string
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow
Take a reference
to a String
23
Lend the string
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow 23
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow 23
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow 23
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow 23
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow 23
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow 23
fn helper(name: &String) {
println!(..);
}
!
!
!
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
Shared borrow 23
Shared == Immutable
24
fn helper(name: &String) {
println!(“{}”, name);
}
fn helper(name: &String) {
name.push_str(“foo”);
}
Shared == Immutable
24
fn helper(name: &String) {
println!(“{}”, name);
}
fn helper(name: &String) {
name.push_str(“foo”);
}
OK. Just reads.
Shared == Immutable
24
fn helper(name: &String) {
println!(“{}”, name);
}
fn helper(name: &String) {
name.push_str(“foo”);
}
OK. Just reads.
Error. Writes.
Shared == Immutable
24
fn helper(name: &String) {
println!(“{}”, name);
}
fn helper(name: &String) {
name.push_str(“foo”);
}
OK. Just reads.
Error. Writes.
error: cannot borrow immutable borrowed content `*name`
as mutable
name.push_str(“s”);
^~~~
Shared == Immutable
24
fn helper(name: &String) {
println!(“{}”, name);
}
fn helper(name: &String) {
name.push_str(“foo”);
}
OK. Just reads.
Error. Writes.
* Actually: mutation only in controlled circumstances.
*
error: cannot borrow immutable borrowed content `*name`
as mutable
name.push_str(“s”);
^~~~
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow
Take a mutable
reference to a String
25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow
Take a mutable
reference to a String
25
Lend the string
mutably
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow
Take a mutable
reference to a String
25
Lend the string
mutably
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow
Take a mutable
reference to a String
25
Lend the string
mutably
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
Mutate string
in place
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
Prints the
updated string.
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
fn update(name: &mut String) {
name.push_str(“…”);
}
!
!
!
fn main() {
let mut name = …;
update(&mut name);
println!(“{}”, name);
}
Mutable borrow 25
Play time
26http://is.gd/no0tTH
.capacity: …
.len: 10
fn helper(name: &String) {
println!(..);
}
!
!
!
27
fn main()
name.data
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
‘R’ ‘u’ … ‘n’ ‘s’
.capacity: …
.len: 10
fn helper(name: &String) {
println!(..);
}
!
!
!
27
fn main()
name.data
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
‘R’ ‘u’ … ‘n’ ‘s’
.capacity: …
.len: 10
fn helper(name: &String) {
println!(..);
}
!
!
!
27
fn main()
name.data
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
‘R’ ‘u’ … ‘n’ ‘s’
.capacity: …
.len: 10
fn helper(name: &String) {
println!(..);
}
!
!
!
27
fn main()
name.data
fn helper()
name
fn main() {
let name = format!(“…”);
helper(&name);
helper(&name);
}
String owned by
somebody else
up the stack.
‘R’ ‘u’ … ‘n’ ‘s’
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
Subslice of a string
owned up the stack
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
helper(&name[1..]);
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
helper(&name[1..]);
“stacean”
7
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
helper(&name[1..]);
“stacean”
7
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
helper(&name[1..]);
“stacean”
7
.capacity: …
.len: 10
fn helper(name: &str) {
!
}
28
fn main()
name.data
fn helper()
name.data
fn main() {
let name = format!(“…”);
helper(&name[1..9]);
helper(&name);
}
.len: 8
‘R’ ‘u’ … ‘n’ ‘s’
“ustacean”
helper(&name[1..]);
“stacean”
7
data
len
data
len
String
data
len
capacity
String
data
len
capacity
‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’
29
“Rustaceans”: &str
format!(“Rustaceans”): String
…Rustaceans…
data
len
data
len
String
data
len
capacity
String
data
len
capacity
‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’
29
“Rustaceans”: &str
format!(“Rustaceans”): String
…Rustaceans…
data
len
data
len
String
data
len
capacity
String
data
len
capacity
‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’
29
“Rustaceans”: &str
format!(“Rustaceans”): String
…Rustaceans…
data
len
data
len
String
data
len
capacity
String
data
len
capacity
‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’
29
“Rustaceans”: &str
format!(“Rustaceans”): String
…Rustaceans…
data
len
data
len
String
data
len
capacity
String
data
len
capacity
‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’
29
“Rustaceans”: &str
format!(“Rustaceans”): String
…Rustaceans…
data
len
data
len
String
data
len
capacity
String
data
len
capacity
‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’
29
“Rustaceans”: &str
format!(“Rustaceans”): String
…Rustaceans…
&’static str
data
len
data
len
String
data
len
capacity
String
data
len
capacity
‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’
29
“Rustaceans”: &str
format!(“Rustaceans”): String
…Rustaceans…
&’static str
Whither Safety?
30https://www.flickr.com/photos/langtind/2217639550/in/photostream/
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
GC vs C++ vs Rust
31
GC’d language (e.g. Java)
One size fits all
`void helper(String name)`
temporary access?
start a thread?
store in a static?
Rust
Temporary references — confined to owner’s scope
Data cannot be freed or mutated while reference is live
C++
No clear rules
Easily invalidated
“Don’t make mistakes”
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
Dangling
reference!
.capacity: …
.len: 10
name.data ‘R’ ‘u’ … ‘n’ ‘s’
32
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
r
Dangling
reference!
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33http://is.gd/HJyO7A
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33http://is.gd/HJyO7A
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33
Lifetime: span of code where reference is used.
http://is.gd/HJyO7A
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33
Lifetime: span of code where reference is used.
http://is.gd/HJyO7A
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33
Lifetime: span of code where reference is used.
http://is.gd/HJyO7A
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33
Lifetime: span of code where reference is used.
http://is.gd/HJyO7A
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33
Lifetime: span of code where reference is used.
http://is.gd/HJyO7A
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33
Lifetime: span of code where reference is used.
http://is.gd/HJyO7A
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33
‘l
Lifetime: span of code where reference is used.
http://is.gd/HJyO7A
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33
‘l
Lifetime: span of code where reference is used.
Scope of data being borrowed (here, `name`)
compared against
http://is.gd/HJyO7A
‘s
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33
‘l
Lifetime: span of code where reference is used.
Scope of data being borrowed (here, `name`)
compared against
http://is.gd/HJyO7A
‘s
fn main() {
let r;
{
let name = format!(“…”);
r = &name;
}
println!(“{}”, r);
}
33
‘l
Lifetime: span of code where reference is used.
Scope of data being borrowed (here, `name`)
compared against
http://is.gd/HJyO7A
error: `name` does not live long enough
r = &name;
^~~~
34
use std::thread;
!
fn helper(name: &String) {
thread::spawn(move || {
use(name);
});
}
34
use std::thread;
!
fn helper(name: &String) {
thread::spawn(move || {
use(name);
});
}
`name` can only be
used within this fn
34
use std::thread;
!
fn helper(name: &String) {
thread::spawn(move || {
use(name);
});
}
`name` can only be
used within this fn
34
use std::thread;
!
fn helper(name: &String) {
thread::spawn(move || {
use(name);
});
}
`name` can only be
used within this fn
34
use std::thread;
!
fn helper(name: &String) {
thread::spawn(move || {
use(name);
});
}
`name` can only be
used within this fn
Might escape
the function!
34
use std::thread;
!
fn helper(name: &String) {
thread::spawn(move || {
use(name);
});
}
`name` can only be
used within this fn
Might escape
the function!
error: the type `[…]` does not fulfill the required lifetime
thread::spawn(move || {
^~~~~~~~~~~~~
note: type must outlive the static lifetime
34
use std::thread;
!
fn helper(name: &String) {
thread::spawn(move || {
use(name);
});
}
`name` can only be
used within this fn
error: the type `[…]` does not fulfill the required lifetime
thread::spawn(move || {
^~~~~~~~~~~~~
note: type must outlive the static lifetime
34
use std::thread;
!
fn helper(name: &String) {
thread::spawn(move || {
use(name);
});
}
`name` can only be
used within this fn
error: the type `[…]` does not fulfill the required lifetime
thread::spawn(move || {
^~~~~~~~~~~~~
note: type must outlive the static lifetime
34
use std::thread;
!
fn helper(name: &String) {
thread::spawn(move || {
use(name);
});
}
`name` can only be
used within this fn
error: the type `[…]` does not fulfill the required lifetime
thread::spawn(move || {
^~~~~~~~~~~~~
note: type must outlive the static lifetime
34
use std::thread;
!
fn helper(name: &String) {
thread::spawn(move || {
use(name);
});
}
`name` can only be
used within this fn
error: the type `[…]` does not fulfill the required lifetime
thread::spawn(move || {
^~~~~~~~~~~~~
note: type must outlive the static lifetime
However: see crossbeam,
simple_parallel, etc on
crates.io
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
‘R’ ‘u’ … ‘n’
String
data
len
capacity
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
‘R’ ‘u’ … ‘n’
String
data
len
capacity
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
‘R’ ‘u’ … ‘n’
String
data
len
capacity
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
‘R’ ‘u’ … ‘n’
String
data
len
capacity
data
len
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
‘R’ ‘u’ … ‘n’
String
data
len
capacity
data
len
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
‘R’ ‘u’ … ‘n’
String
data
len
capacity
data
len
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
‘R’ ‘u’ … ‘n’
String
data
len
capacity
‘R’ ‘u’ … ‘n’
data
len
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
‘R’ ‘u’ … ‘n’
String
data
len
capacity
‘R’ ‘u’ … ‘n’
data
len
‘s’
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
String
data
len
capacity
‘R’ ‘u’ … ‘n’
data
len
‘R’ ‘u’ … ‘n’
‘s’
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
String
data
len
capacity
‘R’ ‘u’ … ‘n’
data
len
‘R’ ‘u’ … ‘n’
‘s’
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
String
data
len
capacity
‘R’ ‘u’ … ‘n’
data
len
‘R’ ‘u’ … ‘n’
‘s’
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
String
data
len
capacity
‘R’ ‘u’ … ‘n’
data
len
‘R’ ‘u’ … ‘n’
‘s’
Dangling
reference!
Dangers of mutation
35
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
String
data
len
capacity
‘R’ ‘u’ … ‘n’
data
len
‘R’ ‘u’ … ‘n’
‘s’
Dangling
reference!
Rust solution
36
Compile-time read-write-lock:!
!
Creating a shared reference to X “read locks” X.
- Other readers OK.
- No writers.
- Lock lasts until reference goes out of scope.
!
Creating a mutable reference to X “writes locks” X.
- No other readers or writers.
- Lock lasts until reference goes out of scope.
Never have a reader/writer at same time.
Dangers of mutation
37
fn main() {
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
http://is.gd/MCPVWg
Dangers of mutation
37
fn main() {
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
http://is.gd/MCPVWg
Dangers of mutation
37
fn main() {
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
Borrow “locks”
`buffer` until `slice`
goes out of scope
http://is.gd/MCPVWg
Dangers of mutation
37
fn main() {
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
Borrow “locks”
`buffer` until `slice`
goes out of scope
http://is.gd/MCPVWg
Dangers of mutation
37
fn main() {
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
Borrow “locks”
`buffer` until `slice`
goes out of scope
error: cannot borrow `buffer` as mutable
because it is also borrowed as immutable
buffer.push_str(“s”);
^~~~~~
http://is.gd/MCPVWg
Dangers of mutation
37
fn main() {
let mut buffer: String = format!(“Rustacean”);
let slice = &buffer[1..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
Borrow “locks”
`buffer` until `slice`
goes out of scope
error: cannot borrow `buffer` as mutable
because it is also borrowed as immutable
buffer.push_str(“s”);
^~~~~~
http://is.gd/MCPVWg
fn main() {
let mut buffer: String = format!(“Rustacean”);
for i in 0 .. buffer.len() {
let slice = &buffer[i..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
buffer.push_str(“s”);
}
38
fn main() {
let mut buffer: String = format!(“Rustacean”);
for i in 0 .. buffer.len() {
let slice = &buffer[i..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
buffer.push_str(“s”);
}
38
Borrow “locks”
`buffer` until `slice`
goes out of scope
fn main() {
let mut buffer: String = format!(“Rustacean”);
for i in 0 .. buffer.len() {
let slice = &buffer[i..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
buffer.push_str(“s”);
}
38
Borrow “locks”
`buffer` until `slice`
goes out of scope
fn main() {
let mut buffer: String = format!(“Rustacean”);
for i in 0 .. buffer.len() {
let slice = &buffer[i..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
buffer.push_str(“s”);
}
38
Borrow “locks”
`buffer` until `slice`
goes out of scope
fn main() {
let mut buffer: String = format!(“Rustacean”);
for i in 0 .. buffer.len() {
let slice = &buffer[i..];
buffer.push_str(“s”);
println!(“{:?}”, slice);
}
buffer.push_str(“s”);
}
38
Borrow “locks”
`buffer` until `slice`
goes out of scope
OK: `buffer` is not borrowed here
Exercise: borrowing
39
http://smallcultfollowing.com/20151209
Cheat sheet:
&String // type of shared reference
&mut String // type of mutable reference
&str // type of string slice
!
&name // shared borrow
&mut name // mutable borrow
&name[x..y] // slice expression
http://doc.rust-lang.org/std
40
Structs and such
41
Shop till you drop!
By QuentinUK (Own work), via Wikimedia Commons
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
name
prices
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
name
prices
.length
.data
.capacity
.length
.data
.capacity
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Item
name
prices
‘R’ ‘u’ … ‘n’
Item
Item
.length
.data
.capacity
.length
.data
.capacity
Declaring a structure
42
struct Store {
name: String,
prices: Vec<Item>,
}
Item
name
prices
‘R’ ‘u’ … ‘n’
Item
Item
.length
.data
.capacity
.length
.data
.capacity
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
43
struct Item {
name: &’static str,
price: f32,
}
Other fundamental types
f32
f64
!
!
i8
i16
i32
i64
isize
u8
u16
u32
u64
usize
&str
&[T]
!
!
floats signed unsigned slices
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
store.add_item(…); // must be let mut
store.price(…); // let OR let mut
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
store.add_item(…); // must be let mut
store.price(…); // let OR let mut
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
store.add_item(…); // must be let mut
store.price(…); // let OR let mut
itself an &mut method
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
store.add_item(…); // must be let mut
store.price(…); // let OR let mut
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
store.add_item(…); // must be let mut
store.price(…); // let OR let mut
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
store.add_item(…); // must be let mut
store.price(…); // let OR let mut
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
store.add_item(…); // must be let mut
store.price(…); // let OR let mut
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
store.add_item(…); // must be let mut
store.price(…); // let OR let mut
Methods
44
struct Store { .. }
struct Item { .. }
!
impl Store {
fn add_item(&mut self, item: Item) {
self.items.push(item);
}
!
fn price(&self, item_name: &str) -> f32 {
… // see upcoming slide
}
}
store.add_item(…); // must be let mut
store.price(…); // let OR let mut
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Store::new(some_name)
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Store::new(some_name)
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Store::new(some_name)
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Store::new(some_name)
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Store::new(some_name)
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Store::new(some_name)
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Store::new(some_name)
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Store::new(some_name)
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Store::new(some_name)
Methods
45
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
return Store {
name: name,
items: vec![],
};
}
}
Store::new(some_name)
Return is optional
46
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
Store {
name: name,
items: vec![],
}
}
}
Return is optional
46
struct Store { .. }
!
impl Store {
fn new(name: String) -> Store {
Store {
name: name,
items: vec![],
}
}
}
No `;` on last expression:
“return this value”
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
Options and Enums
47
enum Option<T> {
Some(T),
None
}
fn main() {
let v: Option<i32> = Some(22);
match v {
Some(x) => println!(“v = {}”, x),
None => println!(“v = None”),
}
println!(“v = {}”, v.unwrap()); // risky
}
http://is.gd/Gfum32
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Alpha”
“Beta”
“Gamma”
v: s:
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Alpha”
“Beta”
“Gamma”
v: s:
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Alpha”
“Beta”
“Gamma”
v: s:
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Alpha”
“Beta”
“Gamma”
v: s:
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Alpha”
“Beta”
“Gamma”
v: s:
Vec<String>
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Alpha”
“Beta”
“Gamma”
v: s:
String
Vec<String>
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Alpha”
“Beta”
“Gamma”
v: s:
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Alpha”
“Beta”
“Gamma”
v: s:
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Beta”
“Gamma”
v: s:
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Beta”
“Gamma”
v: s:
For Loops
48
fn main() {
let v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
for s in v {
println!(“{:?}”, s);
}
}
http://is.gd/6kJc0O
“Gamma”
v: s:
For Loops
49
fn main() {
let mut v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
!
for s in &v {
println!(“{:?}”, s);
}
!
for s in &mut v {
s.push_str(“.”);
}
}
“Alpha”
“Beta”
“Gamma”
v:
For Loops
49
fn main() {
let mut v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
!
for s in &v {
println!(“{:?}”, s);
}
!
for s in &mut v {
s.push_str(“.”);
}
}
“Alpha”
“Beta”
“Gamma”
v:
For Loops
49
fn main() {
let mut v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
!
for s in &v {
println!(“{:?}”, s);
}
!
for s in &mut v {
s.push_str(“.”);
}
}
“Alpha”
“Beta”
“Gamma”
v:
&Vec<String>
For Loops
49
fn main() {
let mut v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
!
for s in &v {
println!(“{:?}”, s);
}
!
for s in &mut v {
s.push_str(“.”);
}
}
“Alpha”
“Beta”
“Gamma”
v:
&String
&Vec<String>
For Loops
49
fn main() {
let mut v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
!
for s in &v {
println!(“{:?}”, s);
}
!
for s in &mut v {
s.push_str(“.”);
}
}
“Alpha”
“Beta”
“Gamma”
v:
For Loops
49
fn main() {
let mut v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
!
for s in &v {
println!(“{:?}”, s);
}
!
for s in &mut v {
s.push_str(“.”);
}
}
“Alpha”
“Beta”
“Gamma”
v:
s:
For Loops
49
fn main() {
let mut v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
!
for s in &v {
println!(“{:?}”, s);
}
!
for s in &mut v {
s.push_str(“.”);
}
}
“Alpha”
“Beta”
“Gamma”
v:
s:
For Loops
49
fn main() {
let mut v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
!
for s in &v {
println!(“{:?}”, s);
}
!
for s in &mut v {
s.push_str(“.”);
}
}
“Alpha”
“Beta”
“Gamma”
v:
s:
For Loops
49
fn main() {
let mut v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
!
for s in &v {
println!(“{:?}”, s);
}
!
for s in &mut v {
s.push_str(“.”);
}
}
“Alpha”
“Beta”
“Gamma”
v:
s:
&mut Vec<String>
&mut String
For Loops
49
fn main() {
let mut v = vec![format!(“Alpha”),
format!(“Beta”),
format!(“Gamma”)];
!
for s in &v {
println!(“{:?}”, s);
}
!
for s in &mut v {
s.push_str(“.”);
}
}
“Alpha”
“Beta”
“Gamma”
v:
s:
Exercise: structs
50
http://smallcultfollowing.com/20151209
Implement
fn total_price(..)
Cheat sheet:
for s in v { … }
for s in &v { … }
let mut some_var = 0.0;
println!(“{:?}”, s);
some_var += x;
while … { … }
http://doc.rust-lang.org/std
51
Threading
Multiparadigm
52
Multiparadigm
Multiparadigm
52
Multiparadigm
message-passing
Multiparadigm
52
Multiparadigm
mutable shared memorymessage-passing
53
53
$5.0
$25.5
$81.5
———
$112.0
53
$5.0
$25.5
$81.5
———
$112.0
$5.0
$20.5
$81.5
———
$107.0
53
$5.0
$25.5
$81.5
———
$112.0
$5.0
$20.5
$81.5
———
$107.0
$5.0
$23.5
XXX
———
XXX
53
$5.0
$25.5
$81.5
———
$112.0
$5.0
$20.5
$81.5
———
$107.0
$5.0
$23.5
XXX
———
XXX
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
54
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
55
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
55
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
55
let mut best = None;
let mut best_price = INFINITY;
for store in stores {
let sum = store.total_price(&shopping_list);
match sum {
Some(s) if s < best_price => {
best = Some(store.name);
best_price = s;
}
_ => { }
}
}
55
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
Closure
takes ownership
of variables it uses.
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
Closure
takes ownership
of variables it uses.
Variables used by
this closure.
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
Closure
takes ownership
of variables it uses.
Variables used by
this closure.
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
Handle to the
thread we spawned.
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
Closure body can
produce a result,
here a (String, f32).
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
use std::thread;
…
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
56
57
let handle = thread::spawn(…);
57
let handle = thread::spawn(…);
57
let handle = thread::spawn(…);
… // stuff in parallel
// with new thread
57
let handle = thread::spawn(…);
… // stuff in parallel
// with new thread
let (name, sum) = handle.join().unwrap();
57
let handle = thread::spawn(…);
… // stuff in parallel
// with new thread
let (name, sum) = handle.join().unwrap();
57
let handle = thread::spawn(…);
… // stuff in parallel
// with new thread
let (name, sum) = handle.join().unwrap();
Wait for thread
to finish and
get return value.
57
let handle = thread::spawn(…);
… // stuff in parallel
// with new thread
let (name, sum) = handle.join().unwrap();
Wait for thread
to finish and
get return value.
Result<(String, f32), Error>
57
let handle = thread::spawn(…);
… // stuff in parallel
// with new thread
let (name, sum) = handle.join().unwrap();
Wait for thread
to finish and
get return value.
Thread may have
panicked. Propagate.
57
let handle = thread::spawn(…);
… // stuff in parallel
// with new thread
let (name, sum) = handle.join().unwrap();
Wait for thread
to finish and
get return value.
Thread may have
panicked. Propagate.Result of thread.
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
58
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
handles.push(
thread::spawn(move || {
let sum = …;
(store.name, sum)
});
}
!
for handle in handles {
let (name, sum) =
handle.join().unwrap();
// find best price
}
59
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
59
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
Variables used by
this closure.
59
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
59
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
59
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
59
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
59
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
error: capture of moved value: `shopping_list`
let sum = store.total_price(&shopping_list);
^~~~~~~~~~~~~
…
help: perhaps you meant to use `clone()`?
59
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
error: capture of moved value: `shopping_list`
let sum = store.total_price(&shopping_list);
^~~~~~~~~~~~~
…
help: perhaps you meant to use `clone()`?
60
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
60
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
60
use std::thread;
…
let shopping_list = vec![…];
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
arc1
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
arc1
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
arc1
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
arc1
arc2
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
arc1
arc2
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
arc1
arc2
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
arc1
arc2
data
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
arc1
arc2
data
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
arc1
arc2
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
arc1
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
61
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let arc2 = arc1.clone();
let data = &arc1[0];
Arc => Immutable
62
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let data = &mut arc1[0];
http://is.gd/nP3Pvb
Arc => Immutable
62
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let data = &mut arc1[0];
http://is.gd/nP3Pvb
Arc => Immutable
62
use std::sync::Arc;
let shopping_list: Vec<ShoppingList> = …;
let arc1 = Arc::new(shopping_list);
let data = &mut arc1[0];
<anon>:6:21: 6:24 error: cannot borrow immutable borrowed
content as mutable
<anon>:6 let data = &mut arc[0];
^~~
http://is.gd/nP3Pvb
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
63
use std::thread;
…
let shopping_list = Arc::new(vec![…]);
let mut handles = vec![];
for store in stores {
let shopping_list = shopping_list.clone();
let handle =
thread::spawn(move || {
let sum = store.total_price(shopping_list);
(store.name, sum)
});
handles.push(handle);
}
// exercise (in a bit): join the handles!
Channels
64
65
Joining a thread allows
thread to send one result.
What if we wanted
multiple results?
65
Joining a thread allows
thread to send one result.
What if we wanted
multiple results?
65
Joining a thread allows
thread to send one result.
What if we wanted
multiple results?
65
Joining a thread allows
thread to send one result.
What if we wanted
multiple results?
65
Joining a thread allows
thread to send one result.
What if we wanted
multiple results?
65
Joining a thread allows
thread to send one result.
What if we wanted
multiple results?
65
Joining a thread allows
thread to send one result.
What if we wanted
multiple results?
Or if we wanted
a response?
65
Joining a thread allows
thread to send one result.
What if we wanted
multiple results?
Or if we wanted
a response?
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
rx
tx
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
rx
tx
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
rx
tx
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
rx
tx
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
rx
tx
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
rx
tx
tx
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
rx
tx
tx
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
MessageMessage
rx
tx
tx
m
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
MessageMessage
rx
tx
tx
m
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
Message
Message
rx
tx
tx
m
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
Message
Message
rx
tx
tx
m
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
Message
Message
rx
tx
tx
m
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
Message
Message
rx
tx
tx
m
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
Message
Message
rx
tx
tx
m
fn parent() {
let (tx, rx) = channel();
spawn(move || {…});
let m = rx.recv().unwrap();
}
66
move || {
let m = Message::new();
…
tx.send(m).unwrap();
}
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
tx1
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
tx1
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
tx1
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
tx1
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
tx1
tx2
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
tx1
tx2
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
tx1
tx2
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
tx1
tx2
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
tx1
tx2
67
rx0
tx0
let (tx0, rx0) = channel();
let tx1 = tx0.clone();
spawn(move || /* omitted */);
let tx2 = tx0.clone();
spawn(move || /* omitted */);
tx1
tx2
Locks
68
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
data
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
data
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
data
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
data
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
1
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
data
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
1
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
data
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
1
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
1
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
1
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
1
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
1
0
69
fn sync_inc(counter: &Arc<Mutex<i32>>) {
let mut data = counter.lock().unwrap();
*data += 1;
}
counter
https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
1
Exercise: threads
70
http://smallcultfollowing.com/20151209
Cheat sheet:
let (name, sum) = thread.join().unwrap();
http://doc.rust-lang.org/std
use std::sync::mpsc::channel;
let (rx, tx) = channel();
tx.send(value).unwrap();
let value = rx.recv().unwrap();
use std::sync::{Arc, Mutex};
let mutex = Arc::new(Mutex::new(data));
let data = mutex.lock().unwrap();
Plea for help
71
Please fill out the
feedback form found at
http://smallcultfollowing.com/20151209
72
72
Thanks for listening!

More Related Content

PDF
Rust concurrency tutorial 2015 12-02
ODP
Rust言語紹介
PDF
Introduction to Rust
PDF
Guaranteeing Memory Safety in Rust
PDF
Rust tutorial from Boston Meetup 2015-07-22
PPTX
Introduction to Rust language programming
PDF
Rust: Reach Further (from QCon Sao Paolo 2018)
Rust concurrency tutorial 2015 12-02
Rust言語紹介
Introduction to Rust
Guaranteeing Memory Safety in Rust
Rust tutorial from Boston Meetup 2015-07-22
Introduction to Rust language programming
Rust: Reach Further (from QCon Sao Paolo 2018)

What's hot (20)

PDF
Intro to Rust from Applicative / NY Meetup
PDF
Rust: Unlocking Systems Programming
PDF
Rust "Hot or Not" at Sioux
PDF
Why rust?
PDF
Rust Workshop - NITC FOSSMEET 2017
PDF
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
PDF
Ownership System in Rust
PPTX
Python
PDF
NativeBoost
PDF
Степан Кольцов — Rust — лучше, чем C++
PDF
JavaScript - new features in ECMAScript 6
PDF
Protocol handler in Gecko
PDF
Python Asíncrono - Async Python
PDF
The Ring programming language version 1.5.3 book - Part 25 of 184
PPT
Python in 90mins
PPT
C++totural file
PDF
Coroutines in Kotlin. UA Mobile 2017.
PPT
PPTX
What the &~#@&lt;!? (Pointers in Rust)
Intro to Rust from Applicative / NY Meetup
Rust: Unlocking Systems Programming
Rust "Hot or Not" at Sioux
Why rust?
Rust Workshop - NITC FOSSMEET 2017
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Ownership System in Rust
Python
NativeBoost
Степан Кольцов — Rust — лучше, чем C++
JavaScript - new features in ECMAScript 6
Protocol handler in Gecko
Python Asíncrono - Async Python
The Ring programming language version 1.5.3 book - Part 25 of 184
Python in 90mins
C++totural file
Coroutines in Kotlin. UA Mobile 2017.
What the &~#@&lt;!? (Pointers in Rust)

Similar to Rust Mozlando Tutorial (20)

PDF
Rustlabs Quick Start
PDF
Who go Types in my Systems Programing!
PDF
Le langage rust
PDF
Introduction to Rust Programming Language
PPTX
Tour of Rust
PDF
Rust: Reach Further
PDF
An introduction to Rust: the modern programming language to develop safe and ...
PDF
The_Borrow_Checker.pdf
PDF
Briefly Rust - Daniele Esposti - Codemotion Rome 2017
PPTX
Explorando el Diseño de la Memoria en Rust
PDF
Rust Intro @ Roma Rust meetup
PDF
Short intro to the Rust language
PDF
Deep drive into rust programming language
PDF
Introduce to Rust-A Powerful System Language
PDF
Go is geting Rusty
PDF
Introduction to Rust - Waterford Tech Meetup 2025
PPTX
Briefly Rust
PPTX
Rust Intro
PDF
Rust & Gamedev
PDF
Meetup di Gruppo Game Jam Roma - Giorgio Pomettini - Codemotion Rome 2018
Rustlabs Quick Start
Who go Types in my Systems Programing!
Le langage rust
Introduction to Rust Programming Language
Tour of Rust
Rust: Reach Further
An introduction to Rust: the modern programming language to develop safe and ...
The_Borrow_Checker.pdf
Briefly Rust - Daniele Esposti - Codemotion Rome 2017
Explorando el Diseño de la Memoria en Rust
Rust Intro @ Roma Rust meetup
Short intro to the Rust language
Deep drive into rust programming language
Introduce to Rust-A Powerful System Language
Go is geting Rusty
Introduction to Rust - Waterford Tech Meetup 2025
Briefly Rust
Rust Intro
Rust & Gamedev
Meetup di Gruppo Game Jam Roma - Giorgio Pomettini - Codemotion Rome 2018

Recently uploaded (20)

PPTX
Greedy best-first search algorithm always selects the path which appears best...
PDF
Top 10 Project Management Software for Small Teams in 2025.pdf
PPTX
Streamlining Project Management in the AV Industry with D-Tools for Zoho CRM ...
PDF
C language slides for c programming book by ANSI
PDF
IDM Crack Activation Key 2025 Free Download
PPTX
Relevance Tuning with Genetic Algorithms
PPTX
SAP Business AI_L1 Overview_EXTERNAL.pptx
PDF
How to Set Realistic Project Milestones and Deadlines
PDF
Difference Between Website and Web Application.pdf
PPTX
Empowering Asian Contributions: The Rise of Regional User Groups in Open Sour...
PDF
SBOM Document Quality Guide - OpenChain SBOM Study Group
PDF
Module 1 - Introduction to Generative AI.pdf
PDF
Ragic Data Security Overview: Certifications, Compliance, and Network Safegua...
PPT
chapter01_java_programming_object_oriented
PPTX
Presentation - Summer Internship at Samatrix.io_template_2.pptx
PDF
OpenEXR Virtual Town Hall - August 2025
PPTX
Comprehensive Guide to Digital Image Processing Concepts and Applications
PDF
OpenAssetIO Virtual Town Hall - August 2025.pdf
PDF
OpenColorIO Virtual Town Hall - August 2025
PDF
Coding with GPT-5- What’s New in GPT 5 That Benefits Developers.pdf
Greedy best-first search algorithm always selects the path which appears best...
Top 10 Project Management Software for Small Teams in 2025.pdf
Streamlining Project Management in the AV Industry with D-Tools for Zoho CRM ...
C language slides for c programming book by ANSI
IDM Crack Activation Key 2025 Free Download
Relevance Tuning with Genetic Algorithms
SAP Business AI_L1 Overview_EXTERNAL.pptx
How to Set Realistic Project Milestones and Deadlines
Difference Between Website and Web Application.pdf
Empowering Asian Contributions: The Rise of Regional User Groups in Open Sour...
SBOM Document Quality Guide - OpenChain SBOM Study Group
Module 1 - Introduction to Generative AI.pdf
Ragic Data Security Overview: Certifications, Compliance, and Network Safegua...
chapter01_java_programming_object_oriented
Presentation - Summer Internship at Samatrix.io_template_2.pptx
OpenEXR Virtual Town Hall - August 2025
Comprehensive Guide to Digital Image Processing Concepts and Applications
OpenAssetIO Virtual Town Hall - August 2025.pdf
OpenColorIO Virtual Town Hall - August 2025
Coding with GPT-5- What’s New in GPT 5 That Benefits Developers.pdf

Rust Mozlando Tutorial

  • 3. 2 Systems programming without the hassle crashes heisenbugs fear
  • 4. 2 Systems programming without the hassle crashes heisenbugs fear Parallel!
  • 5. // sums all the positive values in `v` fn sum_pos(v: &[i32]) -> i32 { let mut sum = 0; for i in v.iter().filter(|i| **i > 0) { sum += *i; } sum } High-level coding 3
  • 6. // sums all the positive values in `v` fn sum_pos(v: &[i32]) -> i32 { let mut sum = 0; for i in v.iter().filter(|i| **i > 0) { sum += *i; } sum } High-level coding 3 Iterators. Closures.
  • 7. Assembly code 4 leaq (%rdi,%rsi,4), %rcx xorl %eax, %eax jmp .LBB5_1 .LBB5_3: addl %edx, %eax .align 16, 0x90 .LBB5_1: cmpq %rdi, %rcx je .LBB5_4 movl (%rdi), %edx addq $4, %rdi testl %edx, %edx jle .LBB5_1 jmp .LBB5_3 .LBB5_4: retq
  • 8. fn foo(v: &[i32]) -> i32 { v.iter() .filter(|i| **i > 0) .map(|i| *i) .sum() } Higher-level coding 5 …generates the same assembly code.
  • 9. Safe 6 fn this_wont_compile(v: &mut Vec<i32>) -> i32 { let mut sum = 0; for &i in v.iter() { sum += i; if i > 0 { v.push(0); } } sum }
  • 10. Safe 6 fn this_wont_compile(v: &mut Vec<i32>) -> i32 { let mut sum = 0; for &i in v.iter() { sum += i; if i > 0 { v.push(0); } } sum } Might free underlying buffer.
  • 11. Safe 6 fn this_wont_compile(v: &mut Vec<i32>) -> i32 { let mut sum = 0; for &i in v.iter() { sum += i; if i > 0 { v.push(0); } } sum } error: cannot borrow `*v` as mutable because it is also borrowed as immutable if i > 0 { v.push(0); } ^ note: previous borrow of `*v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `*v` until the borrow ends for &i in v.iter() { ^ Might free underlying buffer.
  • 12. fn parallel_qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); rayon::join( || parallel_qsort(less), || parallel_qsort(greater) ); } Parallel 7Caveat: shameless plug for third-party package of mine.
  • 13. fn parallel_qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); rayon::join( || parallel_qsort(less), || parallel_qsort(greater) ); } Parallel 7 Sort left and right in parallel.Caveat: shameless plug for third-party package of mine.
  • 14. fn parallel_qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); rayon::join( || parallel_qsort(less), || parallel_qsort(less) ); } Parallel… and safe 8 Data race.
  • 15. fn parallel_qsort(vec: &mut [int]) { if vec.len() <= 1 { return; } let pivot = vec[random(vec.len())]; let mid = vec.partition(vec, pivot); let (less, greater) = vec.split_at_mut(mid); rayon::join( || parallel_qsort(less), || parallel_qsort(less) ); } Parallel… and safe 8 error: closure requires unique access to `less` but it is already borrowed || parallel_qsort(less) ^~~~~~~~~~~~~~~~~~~~~~~ Data race.
  • 16. Open and welcoming Rust has been open source from the beginning. ! Open governance model based on public RFCs. ! We have an active, amazing community. ❤ 9
  • 17. The Plan 10 1. Hello, world! 2. Structs and such. 3. Threads.
  • 19. Hello, world! 12 smallcultfollowing.com/20151209/ ! Example “Hello World” fn main() { println!(“Hello, world!”); }
  • 20. Ownership! ! n. The act, state, or right of possessing something. 13 Borrow! ! v. To receive something with the promise of returning it.
  • 26. fn main() { let name = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 27. fn main() { let name = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 28. fn main() { let name = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership Take ownership of a String 16
  • 29. fn main() { let name = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 30. fn main() { let name = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 31. fn main() { let name = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 32. fn main() { let name = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 33. fn main() { let name = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 34. fn main() { let name = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 35. fn main() { let name = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16 Error: use of moved value: `name`
  • 36. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 37. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 38. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java Take reference to Vector 17
  • 39. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 40. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 41. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 42. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 43. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 44. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 45. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 46. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 47. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 48. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17 new Thread(…);
  • 49. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17 new Thread(…);
  • 50. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17 new Thread(…);
  • 51. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17 new Thread(…);
  • 52. void main() { Vector name = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17 new Thread(…);
  • 53. Clone 18 fn main() { let name = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 54. Clone 18 fn main() { let name = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 55. Clone 18 fn main() { let name = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Copy the String
  • 56. Clone 18 fn main() { let name = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 57. Clone 18 fn main() { let name = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 58. Clone 18 fn main() { let name = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 59. Clone 18 fn main() { let name = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 60. Clone 18 fn main() { let name = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 61. Clone 18 fn main() { let name = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 62. Copy (auto-Clone) 19 fn main() { let name = 22; helper(name); helper(name); } fn helper(name: i32) { println!(..); } ! ! !
  • 63. Copy (auto-Clone) 19 fn main() { let name = 22; helper(name); helper(name); } fn helper(name: i32) { println!(..); } ! ! ! i32 is a Copy type
  • 64. Copy (auto-Clone) 19 fn main() { let name = 22; helper(name); helper(name); } fn helper(name: i32) { println!(..); } ! ! ! i32 is a Copy type
  • 65. Copy (auto-Clone) 19 fn main() { let name = 22; helper(name); helper(name); } fn helper(name: i32) { println!(..); } ! ! ! i32 is a Copy type
  • 66. Copy (auto-Clone) 19 fn main() { let name = 22; helper(name); helper(name); } fn helper(name: i32) { println!(..); } ! ! ! i32 is a Copy type
  • 67. Copy (auto-Clone) 19 fn main() { let name = 22; helper(name); helper(name); } fn helper(name: i32) { println!(..); } ! ! ! i32 is a Copy type
  • 68. 20 Non-copyable: Values move from place to place. Examples: File descriptor, database handle. ! Clone: Run custom code to make a copy. Examples: String, Vector! ! Copy: Type is implicitly copied when referenced. Examples: u32, i32, (f32, i32).
  • 69. Exercise: ownership 21 http://smallcultfollowing.com/20151209 Cheat sheet: fn helper(name: String) // takes ownership ! string.clone() // clone the string http://doc.rust-lang.org/std
  • 73. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow 23
  • 74. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow 23
  • 75. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow 23
  • 76. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow Take a reference to a String 23
  • 77. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow Take a reference to a String 23 Lend the string
  • 78. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow Take a reference to a String 23 Lend the string
  • 79. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow Take a reference to a String 23 Lend the string
  • 80. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow 23
  • 81. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow 23
  • 82. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow 23
  • 83. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow 23
  • 84. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow 23
  • 85. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow 23
  • 86. fn helper(name: &String) { println!(..); } ! ! ! fn main() { let name = format!(“…”); helper(&name); helper(&name); } Shared borrow 23
  • 87. Shared == Immutable 24 fn helper(name: &String) { println!(“{}”, name); } fn helper(name: &String) { name.push_str(“foo”); }
  • 88. Shared == Immutable 24 fn helper(name: &String) { println!(“{}”, name); } fn helper(name: &String) { name.push_str(“foo”); } OK. Just reads.
  • 89. Shared == Immutable 24 fn helper(name: &String) { println!(“{}”, name); } fn helper(name: &String) { name.push_str(“foo”); } OK. Just reads. Error. Writes.
  • 90. Shared == Immutable 24 fn helper(name: &String) { println!(“{}”, name); } fn helper(name: &String) { name.push_str(“foo”); } OK. Just reads. Error. Writes. error: cannot borrow immutable borrowed content `*name` as mutable name.push_str(“s”); ^~~~
  • 91. Shared == Immutable 24 fn helper(name: &String) { println!(“{}”, name); } fn helper(name: &String) { name.push_str(“foo”); } OK. Just reads. Error. Writes. * Actually: mutation only in controlled circumstances. * error: cannot borrow immutable borrowed content `*name` as mutable name.push_str(“s”); ^~~~
  • 92. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 93. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 94. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow Take a mutable reference to a String 25
  • 95. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow Take a mutable reference to a String 25 Lend the string mutably
  • 96. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow Take a mutable reference to a String 25 Lend the string mutably
  • 97. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow Take a mutable reference to a String 25 Lend the string mutably
  • 98. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 99. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 100. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 101. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25 Mutate string in place
  • 102. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 103. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 104. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 105. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 106. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 107. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25 Prints the updated string.
  • 108. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 109. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 110. fn update(name: &mut String) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 112. .capacity: … .len: 10 fn helper(name: &String) { println!(..); } ! ! ! 27 fn main() name.data fn main() { let name = format!(“…”); helper(&name); helper(&name); } ‘R’ ‘u’ … ‘n’ ‘s’
  • 113. .capacity: … .len: 10 fn helper(name: &String) { println!(..); } ! ! ! 27 fn main() name.data fn main() { let name = format!(“…”); helper(&name); helper(&name); } ‘R’ ‘u’ … ‘n’ ‘s’
  • 114. .capacity: … .len: 10 fn helper(name: &String) { println!(..); } ! ! ! 27 fn main() name.data fn main() { let name = format!(“…”); helper(&name); helper(&name); } ‘R’ ‘u’ … ‘n’ ‘s’
  • 115. .capacity: … .len: 10 fn helper(name: &String) { println!(..); } ! ! ! 27 fn main() name.data fn helper() name fn main() { let name = format!(“…”); helper(&name); helper(&name); } String owned by somebody else up the stack. ‘R’ ‘u’ … ‘n’ ‘s’
  • 116. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean”
  • 117. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean”
  • 118. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean”
  • 119. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean”
  • 120. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean” Subslice of a string owned up the stack
  • 121. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean”
  • 122. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean” helper(&name[1..]);
  • 123. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean” helper(&name[1..]); “stacean” 7
  • 124. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean” helper(&name[1..]); “stacean” 7
  • 125. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean” helper(&name[1..]); “stacean” 7
  • 126. .capacity: … .len: 10 fn helper(name: &str) { ! } 28 fn main() name.data fn helper() name.data fn main() { let name = format!(“…”); helper(&name[1..9]); helper(&name); } .len: 8 ‘R’ ‘u’ … ‘n’ ‘s’ “ustacean” helper(&name[1..]); “stacean” 7
  • 127. data len data len String data len capacity String data len capacity ‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’ 29 “Rustaceans”: &str format!(“Rustaceans”): String …Rustaceans…
  • 128. data len data len String data len capacity String data len capacity ‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’ 29 “Rustaceans”: &str format!(“Rustaceans”): String …Rustaceans…
  • 129. data len data len String data len capacity String data len capacity ‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’ 29 “Rustaceans”: &str format!(“Rustaceans”): String …Rustaceans…
  • 130. data len data len String data len capacity String data len capacity ‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’ 29 “Rustaceans”: &str format!(“Rustaceans”): String …Rustaceans…
  • 131. data len data len String data len capacity String data len capacity ‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’ 29 “Rustaceans”: &str format!(“Rustaceans”): String …Rustaceans…
  • 132. data len data len String data len capacity String data len capacity ‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’ 29 “Rustaceans”: &str format!(“Rustaceans”): String …Rustaceans… &’static str
  • 133. data len data len String data len capacity String data len capacity ‘R’ ‘u’ … ‘s’‘R’ ‘u’ … ‘s’ 29 “Rustaceans”: &str format!(“Rustaceans”): String …Rustaceans… &’static str
  • 135. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 136. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 137. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 138. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 139. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 140. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 141. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 142. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 143. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 144. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 145. GC vs C++ vs Rust 31 GC’d language (e.g. Java) One size fits all `void helper(String name)` temporary access? start a thread? store in a static? Rust Temporary references — confined to owner’s scope Data cannot be freed or mutated while reference is live C++ No clear rules Easily invalidated “Don’t make mistakes”
  • 146. 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); }
  • 147. 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); }
  • 148. 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 149. 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 150. 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 151. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 152. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 153. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 154. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 155. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 156. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 157. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 158. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 159. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 160. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r Dangling reference!
  • 161. .capacity: … .len: 10 name.data ‘R’ ‘u’ … ‘n’ ‘s’ 32 fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r Dangling reference!
  • 162. fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33http://is.gd/HJyO7A
  • 163. fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33http://is.gd/HJyO7A
  • 164. fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 165. fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 166. fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 167. fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 168. fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 169. fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 170. fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 ‘l Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 171. fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 ‘l Lifetime: span of code where reference is used. Scope of data being borrowed (here, `name`) compared against http://is.gd/HJyO7A
  • 172. ‘s fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 ‘l Lifetime: span of code where reference is used. Scope of data being borrowed (here, `name`) compared against http://is.gd/HJyO7A
  • 173. ‘s fn main() { let r; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 ‘l Lifetime: span of code where reference is used. Scope of data being borrowed (here, `name`) compared against http://is.gd/HJyO7A error: `name` does not live long enough r = &name; ^~~~
  • 174. 34 use std::thread; ! fn helper(name: &String) { thread::spawn(move || { use(name); }); }
  • 175. 34 use std::thread; ! fn helper(name: &String) { thread::spawn(move || { use(name); }); } `name` can only be used within this fn
  • 176. 34 use std::thread; ! fn helper(name: &String) { thread::spawn(move || { use(name); }); } `name` can only be used within this fn
  • 177. 34 use std::thread; ! fn helper(name: &String) { thread::spawn(move || { use(name); }); } `name` can only be used within this fn
  • 178. 34 use std::thread; ! fn helper(name: &String) { thread::spawn(move || { use(name); }); } `name` can only be used within this fn Might escape the function!
  • 179. 34 use std::thread; ! fn helper(name: &String) { thread::spawn(move || { use(name); }); } `name` can only be used within this fn Might escape the function! error: the type `[…]` does not fulfill the required lifetime thread::spawn(move || { ^~~~~~~~~~~~~ note: type must outlive the static lifetime
  • 180. 34 use std::thread; ! fn helper(name: &String) { thread::spawn(move || { use(name); }); } `name` can only be used within this fn error: the type `[…]` does not fulfill the required lifetime thread::spawn(move || { ^~~~~~~~~~~~~ note: type must outlive the static lifetime
  • 181. 34 use std::thread; ! fn helper(name: &String) { thread::spawn(move || { use(name); }); } `name` can only be used within this fn error: the type `[…]` does not fulfill the required lifetime thread::spawn(move || { ^~~~~~~~~~~~~ note: type must outlive the static lifetime
  • 182. 34 use std::thread; ! fn helper(name: &String) { thread::spawn(move || { use(name); }); } `name` can only be used within this fn error: the type `[…]` does not fulfill the required lifetime thread::spawn(move || { ^~~~~~~~~~~~~ note: type must outlive the static lifetime
  • 183. 34 use std::thread; ! fn helper(name: &String) { thread::spawn(move || { use(name); }); } `name` can only be used within this fn error: the type `[…]` does not fulfill the required lifetime thread::spawn(move || { ^~~~~~~~~~~~~ note: type must outlive the static lifetime However: see crossbeam, simple_parallel, etc on crates.io
  • 184. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice);
  • 185. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice);
  • 186. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); ‘R’ ‘u’ … ‘n’ String data len capacity
  • 187. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); ‘R’ ‘u’ … ‘n’ String data len capacity
  • 188. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); ‘R’ ‘u’ … ‘n’ String data len capacity
  • 189. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); ‘R’ ‘u’ … ‘n’ String data len capacity data len
  • 190. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); ‘R’ ‘u’ … ‘n’ String data len capacity data len
  • 191. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); ‘R’ ‘u’ … ‘n’ String data len capacity data len
  • 192. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); ‘R’ ‘u’ … ‘n’ String data len capacity ‘R’ ‘u’ … ‘n’ data len
  • 193. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); ‘R’ ‘u’ … ‘n’ String data len capacity ‘R’ ‘u’ … ‘n’ data len ‘s’
  • 194. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); String data len capacity ‘R’ ‘u’ … ‘n’ data len ‘R’ ‘u’ … ‘n’ ‘s’
  • 195. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); String data len capacity ‘R’ ‘u’ … ‘n’ data len ‘R’ ‘u’ … ‘n’ ‘s’
  • 196. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); String data len capacity ‘R’ ‘u’ … ‘n’ data len ‘R’ ‘u’ … ‘n’ ‘s’
  • 197. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); String data len capacity ‘R’ ‘u’ … ‘n’ data len ‘R’ ‘u’ … ‘n’ ‘s’ Dangling reference!
  • 198. Dangers of mutation 35 let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); String data len capacity ‘R’ ‘u’ … ‘n’ data len ‘R’ ‘u’ … ‘n’ ‘s’ Dangling reference!
  • 199. Rust solution 36 Compile-time read-write-lock:! ! Creating a shared reference to X “read locks” X. - Other readers OK. - No writers. - Lock lasts until reference goes out of scope. ! Creating a mutable reference to X “writes locks” X. - No other readers or writers. - Lock lasts until reference goes out of scope. Never have a reader/writer at same time.
  • 200. Dangers of mutation 37 fn main() { let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); } http://is.gd/MCPVWg
  • 201. Dangers of mutation 37 fn main() { let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); } http://is.gd/MCPVWg
  • 202. Dangers of mutation 37 fn main() { let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); } Borrow “locks” `buffer` until `slice` goes out of scope http://is.gd/MCPVWg
  • 203. Dangers of mutation 37 fn main() { let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); } Borrow “locks” `buffer` until `slice` goes out of scope http://is.gd/MCPVWg
  • 204. Dangers of mutation 37 fn main() { let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); } Borrow “locks” `buffer` until `slice` goes out of scope error: cannot borrow `buffer` as mutable because it is also borrowed as immutable buffer.push_str(“s”); ^~~~~~ http://is.gd/MCPVWg
  • 205. Dangers of mutation 37 fn main() { let mut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice); } Borrow “locks” `buffer` until `slice` goes out of scope error: cannot borrow `buffer` as mutable because it is also borrowed as immutable buffer.push_str(“s”); ^~~~~~ http://is.gd/MCPVWg
  • 206. fn main() { let mut buffer: String = format!(“Rustacean”); for i in 0 .. buffer.len() { let slice = &buffer[i..]; buffer.push_str(“s”); println!(“{:?}”, slice); } buffer.push_str(“s”); } 38
  • 207. fn main() { let mut buffer: String = format!(“Rustacean”); for i in 0 .. buffer.len() { let slice = &buffer[i..]; buffer.push_str(“s”); println!(“{:?}”, slice); } buffer.push_str(“s”); } 38 Borrow “locks” `buffer` until `slice` goes out of scope
  • 208. fn main() { let mut buffer: String = format!(“Rustacean”); for i in 0 .. buffer.len() { let slice = &buffer[i..]; buffer.push_str(“s”); println!(“{:?}”, slice); } buffer.push_str(“s”); } 38 Borrow “locks” `buffer` until `slice` goes out of scope
  • 209. fn main() { let mut buffer: String = format!(“Rustacean”); for i in 0 .. buffer.len() { let slice = &buffer[i..]; buffer.push_str(“s”); println!(“{:?}”, slice); } buffer.push_str(“s”); } 38 Borrow “locks” `buffer` until `slice` goes out of scope
  • 210. fn main() { let mut buffer: String = format!(“Rustacean”); for i in 0 .. buffer.len() { let slice = &buffer[i..]; buffer.push_str(“s”); println!(“{:?}”, slice); } buffer.push_str(“s”); } 38 Borrow “locks” `buffer` until `slice` goes out of scope OK: `buffer` is not borrowed here
  • 211. Exercise: borrowing 39 http://smallcultfollowing.com/20151209 Cheat sheet: &String // type of shared reference &mut String // type of mutable reference &str // type of string slice ! &name // shared borrow &mut name // mutable borrow &name[x..y] // slice expression http://doc.rust-lang.org/std
  • 213. 41 Shop till you drop! By QuentinUK (Own work), via Wikimedia Commons
  • 214. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, }
  • 215. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, }
  • 216. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, }
  • 217. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, }
  • 218. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, }
  • 219. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, }
  • 220. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, }
  • 221. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, }
  • 222. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, }
  • 223. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, } name prices
  • 224. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, } name prices .length .data .capacity .length .data .capacity
  • 225. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, } Item name prices ‘R’ ‘u’ … ‘n’ Item Item .length .data .capacity .length .data .capacity
  • 226. Declaring a structure 42 struct Store { name: String, prices: Vec<Item>, } Item name prices ‘R’ ‘u’ … ‘n’ Item Item .length .data .capacity .length .data .capacity
  • 227. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 228. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 229. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 230. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 231. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 232. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 233. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 234. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 235. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 236. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 237. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 238. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 239. 43 struct Item { name: &’static str, price: f32, } Other fundamental types f32 f64 ! ! i8 i16 i32 i64 isize u8 u16 u32 u64 usize &str &[T] ! ! floats signed unsigned slices
  • 240. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } }
  • 241. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } }
  • 242. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } }
  • 243. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } } store.add_item(…); // must be let mut store.price(…); // let OR let mut
  • 244. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } } store.add_item(…); // must be let mut store.price(…); // let OR let mut
  • 245. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } } store.add_item(…); // must be let mut store.price(…); // let OR let mut itself an &mut method
  • 246. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } } store.add_item(…); // must be let mut store.price(…); // let OR let mut
  • 247. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } } store.add_item(…); // must be let mut store.price(…); // let OR let mut
  • 248. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } } store.add_item(…); // must be let mut store.price(…); // let OR let mut
  • 249. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } } store.add_item(…); // must be let mut store.price(…); // let OR let mut
  • 250. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } } store.add_item(…); // must be let mut store.price(…); // let OR let mut
  • 251. Methods 44 struct Store { .. } struct Item { .. } ! impl Store { fn add_item(&mut self, item: Item) { self.items.push(item); } ! fn price(&self, item_name: &str) -> f32 { … // see upcoming slide } } store.add_item(…); // must be let mut store.price(…); // let OR let mut
  • 252. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } }
  • 253. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } }
  • 254. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } } Store::new(some_name)
  • 255. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } } Store::new(some_name)
  • 256. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } } Store::new(some_name)
  • 257. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } } Store::new(some_name)
  • 258. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } } Store::new(some_name)
  • 259. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } } Store::new(some_name)
  • 260. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } } Store::new(some_name)
  • 261. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } } Store::new(some_name)
  • 262. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } } Store::new(some_name)
  • 263. Methods 45 struct Store { .. } ! impl Store { fn new(name: String) -> Store { return Store { name: name, items: vec![], }; } } Store::new(some_name)
  • 264. Return is optional 46 struct Store { .. } ! impl Store { fn new(name: String) -> Store { Store { name: name, items: vec![], } } }
  • 265. Return is optional 46 struct Store { .. } ! impl Store { fn new(name: String) -> Store { Store { name: name, items: vec![], } } } No `;` on last expression: “return this value”
  • 266. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 267. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 268. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 269. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 270. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 271. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 272. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 273. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 274. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 275. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 276. Options and Enums 47 enum Option<T> { Some(T), None } fn main() { let v: Option<i32> = Some(22); match v { Some(x) => println!(“v = {}”, x), None => println!(“v = None”), } println!(“v = {}”, v.unwrap()); // risky } http://is.gd/Gfum32
  • 277. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Alpha” “Beta” “Gamma” v: s:
  • 278. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Alpha” “Beta” “Gamma” v: s:
  • 279. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Alpha” “Beta” “Gamma” v: s:
  • 280. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Alpha” “Beta” “Gamma” v: s:
  • 281. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Alpha” “Beta” “Gamma” v: s: Vec<String>
  • 282. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Alpha” “Beta” “Gamma” v: s: String Vec<String>
  • 283. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Alpha” “Beta” “Gamma” v: s:
  • 284. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Alpha” “Beta” “Gamma” v: s:
  • 285. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Beta” “Gamma” v: s:
  • 286. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Beta” “Gamma” v: s:
  • 287. For Loops 48 fn main() { let v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; for s in v { println!(“{:?}”, s); } } http://is.gd/6kJc0O “Gamma” v: s:
  • 288. For Loops 49 fn main() { let mut v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &mut v { s.push_str(“.”); } } “Alpha” “Beta” “Gamma” v:
  • 289. For Loops 49 fn main() { let mut v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &mut v { s.push_str(“.”); } } “Alpha” “Beta” “Gamma” v:
  • 290. For Loops 49 fn main() { let mut v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &mut v { s.push_str(“.”); } } “Alpha” “Beta” “Gamma” v: &Vec<String>
  • 291. For Loops 49 fn main() { let mut v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &mut v { s.push_str(“.”); } } “Alpha” “Beta” “Gamma” v: &String &Vec<String>
  • 292. For Loops 49 fn main() { let mut v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &mut v { s.push_str(“.”); } } “Alpha” “Beta” “Gamma” v:
  • 293. For Loops 49 fn main() { let mut v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &mut v { s.push_str(“.”); } } “Alpha” “Beta” “Gamma” v: s:
  • 294. For Loops 49 fn main() { let mut v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &mut v { s.push_str(“.”); } } “Alpha” “Beta” “Gamma” v: s:
  • 295. For Loops 49 fn main() { let mut v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &mut v { s.push_str(“.”); } } “Alpha” “Beta” “Gamma” v: s:
  • 296. For Loops 49 fn main() { let mut v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &mut v { s.push_str(“.”); } } “Alpha” “Beta” “Gamma” v: s: &mut Vec<String> &mut String
  • 297. For Loops 49 fn main() { let mut v = vec![format!(“Alpha”), format!(“Beta”), format!(“Gamma”)]; ! for s in &v { println!(“{:?}”, s); } ! for s in &mut v { s.push_str(“.”); } } “Alpha” “Beta” “Gamma” v: s:
  • 298. Exercise: structs 50 http://smallcultfollowing.com/20151209 Implement fn total_price(..) Cheat sheet: for s in v { … } for s in &v { … } let mut some_var = 0.0; println!(“{:?}”, s); some_var += x; while … { … } http://doc.rust-lang.org/std
  • 303. 53
  • 308. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 309. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 310. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 311. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 312. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 313. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 314. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 315. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 316. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 317. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 318. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 319. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 320. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 321. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 322. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 323. 54 let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } }
  • 324. let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } } 55
  • 325. let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } } 55
  • 326. let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } } 55
  • 327. let mut best = None; let mut best_price = INFINITY; for store in stores { let sum = store.total_price(&shopping_list); match sum { Some(s) if s < best_price => { best = Some(store.name); best_price = s; } _ => { } } } 55
  • 328. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 329. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 330. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 331. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 332. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 333. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 334. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 335. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56 Closure takes ownership of variables it uses.
  • 336. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56 Closure takes ownership of variables it uses. Variables used by this closure.
  • 337. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56 Closure takes ownership of variables it uses. Variables used by this closure.
  • 338. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 339. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56 Handle to the thread we spawned.
  • 340. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 341. Closure body can produce a result, here a (String, f32). use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 342. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 343. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 344. use std::thread; … let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } 56
  • 345. 57 let handle = thread::spawn(…);
  • 346. 57 let handle = thread::spawn(…);
  • 347. 57 let handle = thread::spawn(…); … // stuff in parallel // with new thread
  • 348. 57 let handle = thread::spawn(…); … // stuff in parallel // with new thread let (name, sum) = handle.join().unwrap();
  • 349. 57 let handle = thread::spawn(…); … // stuff in parallel // with new thread let (name, sum) = handle.join().unwrap();
  • 350. 57 let handle = thread::spawn(…); … // stuff in parallel // with new thread let (name, sum) = handle.join().unwrap(); Wait for thread to finish and get return value.
  • 351. 57 let handle = thread::spawn(…); … // stuff in parallel // with new thread let (name, sum) = handle.join().unwrap(); Wait for thread to finish and get return value. Result<(String, f32), Error>
  • 352. 57 let handle = thread::spawn(…); … // stuff in parallel // with new thread let (name, sum) = handle.join().unwrap(); Wait for thread to finish and get return value. Thread may have panicked. Propagate.
  • 353. 57 let handle = thread::spawn(…); … // stuff in parallel // with new thread let (name, sum) = handle.join().unwrap(); Wait for thread to finish and get return value. Thread may have panicked. Propagate.Result of thread.
  • 354. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 355. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 356. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 357. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 358. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 359. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 360. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 361. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 362. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 363. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 364. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 365. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 366. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 367. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 368. 58 let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { handles.push( thread::spawn(move || { let sum = …; (store.name, sum) }); } ! for handle in handles { let (name, sum) = handle.join().unwrap(); // find best price }
  • 369. 59 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 370. 59 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } Variables used by this closure.
  • 371. 59 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 372. 59 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 373. 59 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 374. 59 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 375. 59 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } error: capture of moved value: `shopping_list` let sum = store.total_price(&shopping_list); ^~~~~~~~~~~~~ … help: perhaps you meant to use `clone()`?
  • 376. 59 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } error: capture of moved value: `shopping_list` let sum = store.total_price(&shopping_list); ^~~~~~~~~~~~~ … help: perhaps you meant to use `clone()`?
  • 377. 60 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 378. 60 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 379. 60 use std::thread; … let shopping_list = vec![…]; let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 380. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
  • 381. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
  • 382. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
  • 383. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
  • 384. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
  • 385. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
  • 386. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
  • 387. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
  • 388. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0]; arc1
  • 389. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0]; arc1
  • 390. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0]; arc1
  • 391. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0]; arc1 arc2
  • 392. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0]; arc1 arc2
  • 393. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0]; arc1 arc2
  • 394. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0]; arc1 arc2 data
  • 395. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0]; arc1 arc2 data
  • 396. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0]; arc1 arc2
  • 397. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0]; arc1
  • 398. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
  • 399. 61 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let arc2 = arc1.clone(); let data = &arc1[0];
  • 400. Arc => Immutable 62 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let data = &mut arc1[0]; http://is.gd/nP3Pvb
  • 401. Arc => Immutable 62 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let data = &mut arc1[0]; http://is.gd/nP3Pvb
  • 402. Arc => Immutable 62 use std::sync::Arc; let shopping_list: Vec<ShoppingList> = …; let arc1 = Arc::new(shopping_list); let data = &mut arc1[0]; <anon>:6:21: 6:24 error: cannot borrow immutable borrowed content as mutable <anon>:6 let data = &mut arc[0]; ^~~ http://is.gd/nP3Pvb
  • 403. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 404. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 405. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 406. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 407. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 408. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 409. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 410. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 411. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 412. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 413. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 414. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 415. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 416. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 417. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 418. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 419. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 420. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); }
  • 421. 63 use std::thread; … let shopping_list = Arc::new(vec![…]); let mut handles = vec![]; for store in stores { let shopping_list = shopping_list.clone(); let handle = thread::spawn(move || { let sum = store.total_price(shopping_list); (store.name, sum) }); handles.push(handle); } // exercise (in a bit): join the handles!
  • 423. 65 Joining a thread allows thread to send one result. What if we wanted multiple results?
  • 424. 65 Joining a thread allows thread to send one result. What if we wanted multiple results?
  • 425. 65 Joining a thread allows thread to send one result. What if we wanted multiple results?
  • 426. 65 Joining a thread allows thread to send one result. What if we wanted multiple results?
  • 427. 65 Joining a thread allows thread to send one result. What if we wanted multiple results?
  • 428. 65 Joining a thread allows thread to send one result. What if we wanted multiple results?
  • 429. 65 Joining a thread allows thread to send one result. What if we wanted multiple results? Or if we wanted a response?
  • 430. 65 Joining a thread allows thread to send one result. What if we wanted multiple results? Or if we wanted a response?
  • 431. fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66
  • 432. rx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66
  • 433. rx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66
  • 434. rx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66
  • 435. rx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 436. rx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 437. rx tx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 438. rx tx tx fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 439. MessageMessage rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 440. MessageMessage rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 441. Message Message rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 442. Message Message rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 443. Message Message rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 444. Message Message rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 445. Message Message rx tx tx m fn parent() { let (tx, rx) = channel(); spawn(move || {…}); let m = rx.recv().unwrap(); } 66 move || { let m = Message::new(); … tx.send(m).unwrap(); }
  • 446. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */);
  • 447. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */);
  • 448. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); tx1
  • 449. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); tx1
  • 450. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); tx1
  • 451. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); tx1
  • 452. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); tx1 tx2
  • 453. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); tx1 tx2
  • 454. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); tx1 tx2
  • 455. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); tx1 tx2
  • 456. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); tx1 tx2
  • 457. 67 rx0 tx0 let (tx0, rx0) = channel(); let tx1 = tx0.clone(); spawn(move || /* omitted */); let tx2 = tx0.clone(); spawn(move || /* omitted */); tx1 tx2
  • 459. 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
  • 460. 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
  • 461. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
  • 462. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
  • 463. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
  • 464. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter data https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
  • 465. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter data https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
  • 466. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter data https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg
  • 467. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter data https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg 1
  • 468. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter data https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg 1
  • 469. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter data https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg 1
  • 470. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg 1
  • 471. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg 1
  • 472. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg 1
  • 473. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg 1
  • 474. 0 69 fn sync_inc(counter: &Arc<Mutex<i32>>) { let mut data = counter.lock().unwrap(); *data += 1; } counter https://commons.wikimedia.org/wiki/File:No-DRM_lock.svg 1
  • 475. Exercise: threads 70 http://smallcultfollowing.com/20151209 Cheat sheet: let (name, sum) = thread.join().unwrap(); http://doc.rust-lang.org/std use std::sync::mpsc::channel; let (rx, tx) = channel(); tx.send(value).unwrap(); let value = rx.recv().unwrap(); use std::sync::{Arc, Mutex}; let mutex = Arc::new(Mutex::new(data)); let data = mutex.lock().unwrap();
  • 476. Plea for help 71 Please fill out the feedback form found at http://smallcultfollowing.com/20151209
  • 477. 72