BGRI Global Rust Monitoring: Challenges and Opportunities for Stripe Rust
Rust Mozlando Tutorial
-
Upload
nikomatsakis -
Category
Software
-
view
828 -
download
0
Transcript of Rust Mozlando Tutorial
// 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
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.
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
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
.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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily 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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily 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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily 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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily 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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily 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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily 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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily 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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily 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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily 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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily 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?
RustTemporary references — confined to owner’s scopeData cannot be freed or mutated while reference is live
C++No clear rulesEasily invalidated“Don’t make mistakes”
.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); }); }
`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
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
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(…);
… // 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!
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?
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
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