Rust Mozlando Tutorial

478
1 Hack without fear! Nicholas Matsakis

Transcript of Rust Mozlando Tutorial

1

Hack without fear!

Nicholas Matsakis

2

Systems programming without the hassle

2

Systems programming without the hasslecrashesheisenbugsfear

2

Systems programming without the hasslecrashesheisenbugsfear

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

Ownership15

Ownership15

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

Borrowing22

Borrowing22

Borrowing22

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?

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”

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

41Shop 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

listenin

g!