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!

Rust Mozlando Tutorial

  • 1.
  • 2.
  • 3.
    2 Systems programming withoutthe hassle crashes heisenbugs fear
  • 4.
    2 Systems programming withoutthe hassle crashes heisenbugs fear Parallel!
  • 5.
    // sums allthe 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 allthe 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: &mutVec<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: &mutVec<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: &mutVec<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 Rusthas 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.
  • 18.
  • 19.
    Hello, world! 12 smallcultfollowing.com/20151209/ ! Example “HelloWorld” 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.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
    fn main() { letname = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 27.
    fn main() { letname = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 28.
    fn main() { letname = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership Take ownership of a String 16
  • 29.
    fn main() { letname = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 30.
    fn main() { letname = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 31.
    fn main() { letname = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 32.
    fn main() { letname = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 33.
    fn main() { letname = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 34.
    fn main() { letname = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16
  • 35.
    fn main() { letname = format!(“…”); helper(name); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Ownership 16 Error: use of moved value: `name`
  • 36.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 37.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 38.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java Take reference to Vector 17
  • 39.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 40.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 41.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 42.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 43.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 44.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 45.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 46.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 47.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17
  • 48.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17 new Thread(…);
  • 49.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17 new Thread(…);
  • 50.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17 new Thread(…);
  • 51.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17 new Thread(…);
  • 52.
    void main() { Vectorname = …; helper(name); helper(name); } void helper(Vector name) { … } ! ! ! “Ownership” in Java 17 new Thread(…);
  • 53.
    Clone 18 fn main() { letname = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 54.
    Clone 18 fn main() { letname = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 55.
    Clone 18 fn main() { letname = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! ! Copy the String
  • 56.
    Clone 18 fn main() { letname = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 57.
    Clone 18 fn main() { letname = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 58.
    Clone 18 fn main() { letname = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 59.
    Clone 18 fn main() { letname = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 60.
    Clone 18 fn main() { letname = format!(“…”); helper(name.clone()); helper(name); } fn helper(name: String) { println!(..); } ! ! !
  • 61.
    Clone 18 fn main() { letname = 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 movefrom 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: fnhelper(name: String) // takes ownership ! string.clone() // clone the string http://doc.rust-lang.org/std
  • 70.
  • 71.
  • 72.
  • 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 fnhelper(name: &String) { println!(“{}”, name); } fn helper(name: &String) { name.push_str(“foo”); }
  • 88.
    Shared == Immutable 24 fnhelper(name: &String) { println!(“{}”, name); } fn helper(name: &String) { name.push_str(“foo”); } OK. Just reads.
  • 89.
    Shared == Immutable 24 fnhelper(name: &String) { println!(“{}”, name); } fn helper(name: &String) { name.push_str(“foo”); } OK. Just reads. Error. Writes.
  • 90.
    Shared == Immutable 24 fnhelper(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 fnhelper(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: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 93.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 94.
    fn update(name: &mutString) { 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: &mutString) { 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: &mutString) { 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: &mutString) { 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: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 99.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 100.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 101.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25 Mutate string in place
  • 102.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 103.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 104.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 105.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 106.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 107.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25 Prints the updated string.
  • 108.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 109.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 110.
    fn update(name: &mutString) { name.push_str(“…”); } ! ! ! fn main() { let mut name = …; update(&mut name); println!(“{}”, name); } Mutable borrow 25
  • 111.
  • 112.
    .capacity: … .len: 10 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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 fnhelper(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
  • 134.
  • 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() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); }
  • 147.
    32 fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); }
  • 148.
    32 fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 149.
    32 fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } r
  • 150.
    32 fn main() { letr; { 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() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33http://is.gd/HJyO7A
  • 163.
    fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33http://is.gd/HJyO7A
  • 164.
    fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 165.
    fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 166.
    fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 167.
    fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 168.
    fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 169.
    fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 170.
    fn main() { letr; { let name = format!(“…”); r = &name; } println!(“{}”, r); } 33 ‘l Lifetime: span of code where reference is used. http://is.gd/HJyO7A
  • 171.
    fn main() { letr; { 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() { letr; { 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() { letr; { 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 letmut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice);
  • 185.
    Dangers of mutation 35 letmut buffer: String = format!(“Rustacean”); let slice = &buffer[1..]; buffer.push_str(“s”); println!(“{:?}”, slice);
  • 186.
    Dangers of mutation 35 letmut 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 letmut 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 letmut 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 letmut 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 letmut 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 letmut 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 letmut 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 letmut 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 letmut 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 letmut 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 letmut 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 letmut 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 letmut 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:! ! Creatinga 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 fnmain() { 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 fnmain() { 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 fnmain() { 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 fnmain() { 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 fnmain() { 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 fnmain() { 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() { letmut 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() { letmut 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() { letmut 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() { letmut 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() { letmut 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
  • 212.
  • 213.
    41 Shop till youdrop! By QuentinUK (Own work), via Wikimedia Commons
  • 214.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, }
  • 215.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, }
  • 216.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, }
  • 217.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, }
  • 218.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, }
  • 219.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, }
  • 220.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, }
  • 221.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, }
  • 222.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, }
  • 223.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, } name prices
  • 224.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, } name prices .length .data .capacity .length .data .capacity
  • 225.
    Declaring a structure 42 structStore { name: String, prices: Vec<Item>, } Item name prices ‘R’ ‘u’ … ‘n’ Item Item .length .data .capacity .length .data .capacity
  • 226.
    Declaring a structure 42 structStore { 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 structStore { .. } ! impl Store { fn new(name: String) -> Store { Store { name: name, items: vec![], } } }
  • 265.
    Return is optional 46 structStore { .. } ! impl Store { fn new(name: String) -> Store { Store { name: name, items: vec![], } } } No `;` on last expression: “return this value”
  • 266.
    Options and Enums 47 enumOption<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 enumOption<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 enumOption<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 enumOption<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 enumOption<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 enumOption<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 enumOption<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 enumOption<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 enumOption<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 enumOption<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 enumOption<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(..) Cheatsheet: 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
  • 299.
  • 300.
  • 301.
  • 302.
  • 303.
  • 304.
  • 305.
  • 306.
  • 307.
  • 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 muthandles = 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 muthandles = 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 muthandles = 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 muthandles = 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 muthandles = 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 muthandles = 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 muthandles = 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 muthandles = 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 muthandles = 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 muthandles = 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 muthandles = 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 muthandles = 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 muthandles = 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 producea 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 muthandles = 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 muthandles = 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 muthandles = 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 usestd::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 usestd::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 usestd::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!
  • 422.
  • 423.
    65 Joining a threadallows thread to send one result. What if we wanted multiple results?
  • 424.
    65 Joining a threadallows thread to send one result. What if we wanted multiple results?
  • 425.
    65 Joining a threadallows thread to send one result. What if we wanted multiple results?
  • 426.
    65 Joining a threadallows thread to send one result. What if we wanted multiple results?
  • 427.
    65 Joining a threadallows thread to send one result. What if we wanted multiple results?
  • 428.
    65 Joining a threadallows thread to send one result. What if we wanted multiple results?
  • 429.
    65 Joining a threadallows thread to send one result. What if we wanted multiple results? Or if we wanted a response?
  • 430.
    65 Joining a threadallows 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
  • 458.
  • 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 Pleasefill out the feedback form found at http://smallcultfollowing.com/20151209
  • 477.
  • 478.