Nicholas Matsakis!
Mozilla Research
So, you want more control?
C++?
OMG!
2
Too slow!
Other things you might want:!
• Standalone library, as you would get from C
• Interface with another runtime, e.g. Ruby
  • Use a really cool language :)
My god, it’s full of bugs
3
Dangling pointers
!
Segmentation faults
!
Double frees
!
Uninitialized data
!
Null pointer exceptions
!
Resource leaks (DB handle)
!
Data races
Solved by GC
Not so much.
4
Systems programming without the hassle
crashes!
heisenbugs!
fear
Parallel!
// sums all the positive values in `v`
fn sum_pos(v: &Vec<i32>) -> i32 {
let mut sum = 0;
for i in v.iter().filter(|i| **i > 0) {
sum += *i;
}
sum
}
High-level coding
5
Iterators.
Closures.
Assembly code
6
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: &Vec<i32>) -> i32 {
v.iter()
.filter(|i| **i > 0)
.map(|i| *i)
.sum()
}
Higher-level coding
7
…generates the same assembly code.
Safe
8
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.
Parallel
9
use std::thread;
fn qsort(data: &mut [i32])
if data.len() <= 1 {
return;
}
let mid = partition(data[0], data);
let (left, right) = data.split_at_mut(mid);
let t1 = thread::scoped(|| qsort(left));
qsort(right);
}
Sort left and right
in parallel.Caveat: unstable API.
Open and welcoming
Rust has been open source from the beginning.
!
Open governance model based on public RFCs.
!
We have an active, amazing community.
❤
10
Getting Started
11
You can either install Rust, or
just use play.rust-lang.org
Exercises are available at:
!
http://nikomatsakis.github.io/rust-tutorial-boston-20150722/
Outline
12
1. The big ideas:!
a. Ownership
b. Borrowing
2. Everyday life:!
a. Data types
b. Modules and privacy
c. Cargo
Ownership!
!
n. The act, state, or right of possessing something.
13
Borrow!
!
v. To receive something with the promise of returning it.
The Big Idea
Ownership and borrowing:!
!
1. All memory has a clear owner.
2. Others can borrow from the owner.
3. Owner cannot free or mutate the
memory while it is borrowed.
14
Ownership/Borrowing
Memory
safety
Data-race
freedom
No need for
a runtime
GCC++
15
Clean up the mess
16
http://mylifeandkids.com/messy-house-edition-boys-bedroom-2/
Ownership
17
fn give() {
let mut vec = vec![];
vec.push(1);
vec.push(2);
take(vec);
…
}
fn take(vec: Vec<i32>) {
// …
}
!
!
!
Ownership
Take ownership
of a Vec<i32>
18
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
…
}
vec.push(2);
Compiler enforces moves
fn take(vec: Vec<i32>) {
// …
}
!
!
!Error: vec has been moved
Prevents:
- use after free
- double moves
- …
19
void give() {
Vector vec = …;
vec.add(1);
vec.add(2);
take(vec);
vec.add(3);
}
void take(Vector vec) {
// …
}
!
!
!
“Ownership” in Java
Take reference
to Vector
20
Mutability
21
fn prefix_sum(mut v: Vec<i32>) -> Vec<i32> {
let mut sum = 0;
for i in 0 .. v.len() {
sum += v[i];
v[i] = sum;
}
v
}
http://is.gd/wCtQQZ
1, 2, 3, 4 1, 3, 6, 10
(caller) (prefix sum)
Clone
22
fn main() {
let d = vec![1, 3, 4, 10];
let ps = prefix_sum(d);
println!("prefix sum of {:?} is {:?}",
d, ps);
}
http://is.gd/nbuxdV
Clone
23
fn main() {
let d = vec![1, 3, 4, 10];
let ps = prefix_sum(d.clone());
println!("prefix sum of {:?} is {:?}",
d, ps);
}
http://is.gd/nbuxdV
1, 2, 3, 4 1, 3, 6, 10
(caller) (prefix sum)
1, 2, 3, 4
24
struct Point {
x: u32,
y: u32
}
!
fn area(ul: Point, lr: Point) -> u32 {
(lr.x - ul.x) * (lr.y - ul.y)
}
!
fn main() {
let origin = Point { x: 0, y: 0 };
let unit = Point { x: 1, y: 1 };
let here = Point { x: 5, y: 6 };
println!(“{:?}”, area(origin, unit));
println!(“{:?}”, area(origin, here));
}
Declare a struct
type Point with two
fields, x and y.
// 1
// ?
http://is.gd/5dDnaH
32-bit unsigned integer
“Copy” types
25
#[derive(Copy, Clone)]
struct Point {
x: u32,
y: u32
}
26
Default: Type cannot be copied.
Values move from place to place.
Example: File descriptor.
!
Clone: Type is expensive to copy,
so make it explicit by calling clone().
Example: Vector, hashtable.!
!
Copy: Type is implicitly copied
whenever it is referenced.
Example: u32, i32, Point
27
Exercise #1.
* Actually: mutation only in controlled circumstances
*
Shared borrow (&T)
Sharing Mutation
Mutable borrow (&mut T)
29
Sharing Mutation
30
fn sum(v: Vec<i32>) -> i32 {
let mut s = 0;
for i in 0 .. v.len() {
s += v[i];
}
s
}
!
fn main() {
let v = vec![1, 2, 3];
println!(“{:?}”, sum(v));
}
Take ownership
of a Vec<i32>
Give ownership
31
fn sum(v: &Vec<i32>) -> i32 {
let mut s = 0;
for i in 0 .. v.len() {
s += v[i];
}
s
}
!
fn main() {
let v = vec![1, 2, 3];
println!(“{:?}”, sum(&v));
}
Borrow!
Vec<i32>
Lend the vector
http://is.gd/aHalet
32
fn prefix_sum(v: &mut Vec<i32>) {
let mut s = 0;
for i in 0 .. v.len() {
s += v[i];
v[i] = s;
}
}
!
fn main() {
let mut v = vec![1, 2, 3];
prefix_sum(&mut v);
println!("{:?}", v);
}
Mutable borrow
Mutable loan
http://is.gd/jvKmF2
fn example() {
let mut names = Vec::new();
names.push(..);
names.push(..);
let name = &names[1];
names.push(..);
print(name);
}
names
data
length
capacity
“brson”
“pcwalton”
name
“brson”
“pcwalton”
“acrichto”
Sharing: more than
one pointer to same
memory.
Dangling pointer: pointer
to freed memory.
Mutating the vector
freed old contents.
33
Rust solution
34
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.
fn example() {
let mut names = Vec::new();
names.push(“brson”);
names.push(“pcwalton”);
let name = &names[1];
names.push(“acrichto”);
println!(“{:?}”, name);
}
Borrow “locks”
`names` until `name`
goes out of scopeError: cannot mutate
`names` while borrowed
35
http://is.gd/jeKW1E
Outside of borrow scope — OK.
Scope of borrow
in this case covers
only the loop body.
36
http://is.gd/thMY5N
fn main() {
let mut names = Vec::new();
names.push("brson");
names.push("pcwalton");
for i in 0 .. names.len() {
let name = &names[i];
names.push("acrichto");
println!("{:?}", name);
}
names.push("acrichto");
}
Rust reasons about scopes
37
fn main() {
let mut names = Vec::new();
names.push("brson");
names.push("pcwalton");
for i in 0 .. names.len() {
let name = &names[i];
println!("{:?}", name);
names.push("acrichto");
}
names.push("acrichto");
}
Even though reference is not used,
it is still in scope for the entire block..
http://is.gd/pLE8bb
Take a break.
38
Daily life in Rust
39
Methods
40
struct Point {
x: f32,
y: f32,
}
!
impl Point {
fn new() -> Point {
Point { x: 0.0, y: 0.0 }
}
!
fn negate(&self) -> Point {
Point { x: -self.x, y: -self.y }
}
} http://is.gd/KbbORT
Common derivations
41
#[derive(PartialEq)]
+ #[derive(PartialOrd)]
#[derive(Clone)]
#[derive(Debug)]
x == y, x != y
x < y, x <= y, …
x.clone()
+ #[derive(Copy)] use(x); use(x);
println!(“{:?}”, x);
#[derive(Hash)] HashMap<T>
Enums
42
struct Point {..}
!
enum Shape {
Circle { origin: Point,
radius: f32 },
!
Rectangle { ul: Point,
lr: Point }
}
43
struct Point {..}
!
enum Shape {
Circle { origin: Point, radius: f32 },
Rectangle { ul: Point, lr: Point }
}
!
impl Shape {
fn unit_circle() -> Shape {
Shape::Circle {
origin: Point { x: 0.0, y: 0.0 },
radius: 1.0
}
}
}
const PI: f32 = 3.14159;
impl Shape {
fn area(&self) -> f32 {
match *self {
Shape::Circle { origin: _, radius: r } =>
PI * r * r,
!
Shape::Rectangle { ul, lr } =>
(lr.y - ul.y).abs() * (lr.x - ul.x).abs()
}
}
}
44
http://is.gd/a2YcvG
Option
45
enum Option<T> {
None,
Some(T),
}
No null types
46
class Shape {
Color color;
!
Shape() { }
!
Color getColor(Color default) {
if (color != null)
return color;
return default;
}
}
(Java)
47
struct Shape {
color: Option<Color>
}
!
impl Shape {
fn new() -> Shape {
Shape { color: None }
}
!
fn get_color(&self, default: Color) -> Color {
match self.color {
None => default,
Some(ref c) => c.clone()
}
}
} (Rust)
48
match self.color {
None => default,
Some(ref c) => c.clone()
}
if let Some(ref c) = self.color {
c.clone()
} else {
default
}
self.color.unwrap_or(default)
self.color.unwrap_or_else(|| default)
Slices
49
fn main() {
// Heap-allocated.
let v: Vec<i32> = vec![1, 2, 3, 4];
!
// Reference to one element.
let e: &i32 = &v[1];
!
// Reference to many elements.
let slice: &[i32] = &v[1..3];
}
http://is.gd/QftPT8
Mutable slices
50
fn main() {
// Heap-allocated.
let mut v: Vec<i32> = vec![1, 2, 3, 4];
println!(“v={:?}”, v);
{
let slice = &mut v[..];
slice[1] += 22;
}
println!(“v={:?}”, v);
}
http://is.gd/31rKv5
For loops and slices
51
for x in &v {
// x is an &i32
}
let v: Vec<i32> = vec![1, 2, 3, 4];
for x in &mut v {
// x is an &mut i32
}
for x in v {
// x is an i32
} // v is consumed after loop
for converts its argument into an iterator
using the IntoIterator trait
Iterators
52
struct PlayerScore {
player_name: String,
score: u32
}
!
fn high_scorers(v: Vec<PlayerScore>)
-> Vec<(String, u32)>
{
v.into_iter()
.filter(|ps| ps.score > 20)
.map(|ps| (ps.player_name, ps.score))
.collect()
}
Programming in the large
53
Cargo
54
> cargo new my_project
> cargo new —-bin my_project
> cd my_project
> emacs
Create a template for a new project:
Edit your project:
> cargo build [—-release]
> cargo test
Build and test your project:
http://doc.crates.io/guide.html
Dependencies
55
[package]
name = "hello_world"
version = "0.1.0"
authors = ["Your Name <you@example.com>”]
!
[dependencies]
regex = "0.1.41"
Cargo.toml
lib.rs
extern crate regex;
Modules
56
mod data;
mod code;
lib.rs/main.rs
data/mod.rs
mod point;
mod shape;
data/point.rs
struct Point {
}
::
data
point
shape
code
data/shape/mod.rs
struct Point {
}
Often used to make
a mod test for unit tests,
or for demonstations.
Inline modules
57
mod data {
mod point {
..
}
!
mod shape {
..
}
}
!
mod code {
lib.rs/main.rs Exactly the same as
creating a separate file.
Use
58
::
data
point
shape
code
code.rs
use data::point::Point;
data/mod.rs
use data::point::Point;
use self::point::Point;
data/shape.rs
use data::point::Point;
use super::point::Point;
Privacy
59
Privacy is the default, use pub to override.
pub struct Point {
pub x: f32,
pub y: f32,
}
impl Point {
pub fn m(&self);
}
pub enum Shape {
…
}
pub mod child;
Private means: code in this module or a descendant.
Where to learn more
60
doc.rust-lang.org/book
users.rust-lang.org / IRC / Stackoverflow
doc.rust-lang.org/std
61
Thanks for listening!

Rust tutorial from Boston Meetup 2015-07-22

  • 1.
  • 2.
    So, you wantmore control? C++? OMG! 2 Too slow! Other things you might want:! • Standalone library, as you would get from C • Interface with another runtime, e.g. Ruby   • Use a really cool language :)
  • 3.
    My god, it’sfull of bugs 3 Dangling pointers ! Segmentation faults ! Double frees ! Uninitialized data ! Null pointer exceptions ! Resource leaks (DB handle) ! Data races Solved by GC Not so much.
  • 4.
    4 Systems programming withoutthe hassle crashes! heisenbugs! fear Parallel!
  • 5.
    // sums allthe positive values in `v` fn sum_pos(v: &Vec<i32>) -> i32 { let mut sum = 0; for i in v.iter().filter(|i| **i > 0) { sum += *i; } sum } High-level coding 5 Iterators. Closures.
  • 6.
    Assembly code 6 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
  • 7.
    fn foo(v: &Vec<i32>)-> i32 { v.iter() .filter(|i| **i > 0) .map(|i| *i) .sum() } Higher-level coding 7 …generates the same assembly code.
  • 8.
    Safe 8 fn this_wont_compile(v: &mutVec<i32>) -> i32 { let mut sum = 0; for &i in v.iter() { sum += i; if i > 0 { v.push(0); } } sum } error: cannot borrow `*v` as mutable because it is also borrowed as immutable if i > 0 { v.push(0); } ^ note: previous borrow of `*v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `*v` until the borrow ends for &i in v.iter() { ^ Might free underlying buffer.
  • 9.
    Parallel 9 use std::thread; fn qsort(data:&mut [i32]) if data.len() <= 1 { return; } let mid = partition(data[0], data); let (left, right) = data.split_at_mut(mid); let t1 = thread::scoped(|| qsort(left)); qsort(right); } Sort left and right in parallel.Caveat: unstable API.
  • 10.
    Open and welcoming Rusthas been open source from the beginning. ! Open governance model based on public RFCs. ! We have an active, amazing community. ❤ 10
  • 11.
    Getting Started 11 You caneither install Rust, or just use play.rust-lang.org Exercises are available at: ! http://nikomatsakis.github.io/rust-tutorial-boston-20150722/
  • 12.
    Outline 12 1. The bigideas:! a. Ownership b. Borrowing 2. Everyday life:! a. Data types b. Modules and privacy c. Cargo
  • 13.
    Ownership! ! n. The act,state, or right of possessing something. 13 Borrow! ! v. To receive something with the promise of returning it.
  • 14.
    The Big Idea Ownershipand borrowing:! ! 1. All memory has a clear owner. 2. Others can borrow from the owner. 3. Owner cannot free or mutate the memory while it is borrowed. 14
  • 15.
  • 16.
    Clean up themess 16 http://mylifeandkids.com/messy-house-edition-boys-bedroom-2/
  • 17.
  • 18.
    fn give() { letmut vec = vec![]; vec.push(1); vec.push(2); take(vec); … } fn take(vec: Vec<i32>) { // … } ! ! ! Ownership Take ownership of a Vec<i32> 18
  • 19.
    fn give() { letmut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); … } vec.push(2); Compiler enforces moves fn take(vec: Vec<i32>) { // … } ! ! !Error: vec has been moved Prevents: - use after free - double moves - … 19
  • 20.
    void give() { Vectorvec = …; vec.add(1); vec.add(2); take(vec); vec.add(3); } void take(Vector vec) { // … } ! ! ! “Ownership” in Java Take reference to Vector 20
  • 21.
    Mutability 21 fn prefix_sum(mut v:Vec<i32>) -> Vec<i32> { let mut sum = 0; for i in 0 .. v.len() { sum += v[i]; v[i] = sum; } v } http://is.gd/wCtQQZ 1, 2, 3, 4 1, 3, 6, 10 (caller) (prefix sum)
  • 22.
    Clone 22 fn main() { letd = vec![1, 3, 4, 10]; let ps = prefix_sum(d); println!("prefix sum of {:?} is {:?}", d, ps); } http://is.gd/nbuxdV
  • 23.
    Clone 23 fn main() { letd = vec![1, 3, 4, 10]; let ps = prefix_sum(d.clone()); println!("prefix sum of {:?} is {:?}", d, ps); } http://is.gd/nbuxdV 1, 2, 3, 4 1, 3, 6, 10 (caller) (prefix sum) 1, 2, 3, 4
  • 24.
    24 struct Point { x:u32, y: u32 } ! fn area(ul: Point, lr: Point) -> u32 { (lr.x - ul.x) * (lr.y - ul.y) } ! fn main() { let origin = Point { x: 0, y: 0 }; let unit = Point { x: 1, y: 1 }; let here = Point { x: 5, y: 6 }; println!(“{:?}”, area(origin, unit)); println!(“{:?}”, area(origin, here)); } Declare a struct type Point with two fields, x and y. // 1 // ? http://is.gd/5dDnaH 32-bit unsigned integer
  • 25.
  • 26.
    26 Default: Type cannotbe copied. Values move from place to place. Example: File descriptor. ! Clone: Type is expensive to copy, so make it explicit by calling clone(). Example: Vector, hashtable.! ! Copy: Type is implicitly copied whenever it is referenced. Example: u32, i32, Point
  • 27.
  • 28.
    * Actually: mutationonly in controlled circumstances * Shared borrow (&T) Sharing Mutation
  • 29.
    Mutable borrow (&mutT) 29 Sharing Mutation
  • 30.
    30 fn sum(v: Vec<i32>)-> i32 { let mut s = 0; for i in 0 .. v.len() { s += v[i]; } s } ! fn main() { let v = vec![1, 2, 3]; println!(“{:?}”, sum(v)); } Take ownership of a Vec<i32> Give ownership
  • 31.
    31 fn sum(v: &Vec<i32>)-> i32 { let mut s = 0; for i in 0 .. v.len() { s += v[i]; } s } ! fn main() { let v = vec![1, 2, 3]; println!(“{:?}”, sum(&v)); } Borrow! Vec<i32> Lend the vector http://is.gd/aHalet
  • 32.
    32 fn prefix_sum(v: &mutVec<i32>) { let mut s = 0; for i in 0 .. v.len() { s += v[i]; v[i] = s; } } ! fn main() { let mut v = vec![1, 2, 3]; prefix_sum(&mut v); println!("{:?}", v); } Mutable borrow Mutable loan http://is.gd/jvKmF2
  • 33.
    fn example() { letmut names = Vec::new(); names.push(..); names.push(..); let name = &names[1]; names.push(..); print(name); } names data length capacity “brson” “pcwalton” name “brson” “pcwalton” “acrichto” Sharing: more than one pointer to same memory. Dangling pointer: pointer to freed memory. Mutating the vector freed old contents. 33
  • 34.
    Rust solution 34 Compile-time read-write-lock:! ! Creatinga shared reference to X “read locks” X. - Other readers OK. - No writers. - Lock lasts until reference goes out of scope. ! Creating a mutable reference to X “writes locks” X. - No other readers or writers. - Lock lasts until reference goes out of scope. Never have a reader/writer at same time.
  • 35.
    fn example() { letmut names = Vec::new(); names.push(“brson”); names.push(“pcwalton”); let name = &names[1]; names.push(“acrichto”); println!(“{:?}”, name); } Borrow “locks” `names` until `name` goes out of scopeError: cannot mutate `names` while borrowed 35 http://is.gd/jeKW1E
  • 36.
    Outside of borrowscope — OK. Scope of borrow in this case covers only the loop body. 36 http://is.gd/thMY5N fn main() { let mut names = Vec::new(); names.push("brson"); names.push("pcwalton"); for i in 0 .. names.len() { let name = &names[i]; names.push("acrichto"); println!("{:?}", name); } names.push("acrichto"); }
  • 37.
    Rust reasons aboutscopes 37 fn main() { let mut names = Vec::new(); names.push("brson"); names.push("pcwalton"); for i in 0 .. names.len() { let name = &names[i]; println!("{:?}", name); names.push("acrichto"); } names.push("acrichto"); } Even though reference is not used, it is still in scope for the entire block.. http://is.gd/pLE8bb
  • 38.
  • 39.
  • 40.
    Methods 40 struct Point { x:f32, y: f32, } ! impl Point { fn new() -> Point { Point { x: 0.0, y: 0.0 } } ! fn negate(&self) -> Point { Point { x: -self.x, y: -self.y } } } http://is.gd/KbbORT
  • 41.
    Common derivations 41 #[derive(PartialEq)] + #[derive(PartialOrd)] #[derive(Clone)] #[derive(Debug)] x== y, x != y x < y, x <= y, … x.clone() + #[derive(Copy)] use(x); use(x); println!(“{:?}”, x); #[derive(Hash)] HashMap<T>
  • 42.
    Enums 42 struct Point {..} ! enumShape { Circle { origin: Point, radius: f32 }, ! Rectangle { ul: Point, lr: Point } }
  • 43.
    43 struct Point {..} ! enumShape { Circle { origin: Point, radius: f32 }, Rectangle { ul: Point, lr: Point } } ! impl Shape { fn unit_circle() -> Shape { Shape::Circle { origin: Point { x: 0.0, y: 0.0 }, radius: 1.0 } } }
  • 44.
    const PI: f32= 3.14159; impl Shape { fn area(&self) -> f32 { match *self { Shape::Circle { origin: _, radius: r } => PI * r * r, ! Shape::Rectangle { ul, lr } => (lr.y - ul.y).abs() * (lr.x - ul.x).abs() } } } 44 http://is.gd/a2YcvG
  • 45.
  • 46.
    No null types 46 classShape { Color color; ! Shape() { } ! Color getColor(Color default) { if (color != null) return color; return default; } } (Java)
  • 47.
    47 struct Shape { color:Option<Color> } ! impl Shape { fn new() -> Shape { Shape { color: None } } ! fn get_color(&self, default: Color) -> Color { match self.color { None => default, Some(ref c) => c.clone() } } } (Rust)
  • 48.
    48 match self.color { None=> default, Some(ref c) => c.clone() } if let Some(ref c) = self.color { c.clone() } else { default } self.color.unwrap_or(default) self.color.unwrap_or_else(|| default)
  • 49.
    Slices 49 fn main() { //Heap-allocated. let v: Vec<i32> = vec![1, 2, 3, 4]; ! // Reference to one element. let e: &i32 = &v[1]; ! // Reference to many elements. let slice: &[i32] = &v[1..3]; } http://is.gd/QftPT8
  • 50.
    Mutable slices 50 fn main(){ // Heap-allocated. let mut v: Vec<i32> = vec![1, 2, 3, 4]; println!(“v={:?}”, v); { let slice = &mut v[..]; slice[1] += 22; } println!(“v={:?}”, v); } http://is.gd/31rKv5
  • 51.
    For loops andslices 51 for x in &v { // x is an &i32 } let v: Vec<i32> = vec![1, 2, 3, 4]; for x in &mut v { // x is an &mut i32 } for x in v { // x is an i32 } // v is consumed after loop for converts its argument into an iterator using the IntoIterator trait
  • 52.
    Iterators 52 struct PlayerScore { player_name:String, score: u32 } ! fn high_scorers(v: Vec<PlayerScore>) -> Vec<(String, u32)> { v.into_iter() .filter(|ps| ps.score > 20) .map(|ps| (ps.player_name, ps.score)) .collect() }
  • 53.
  • 54.
    Cargo 54 > cargo newmy_project > cargo new —-bin my_project > cd my_project > emacs Create a template for a new project: Edit your project: > cargo build [—-release] > cargo test Build and test your project: http://doc.crates.io/guide.html
  • 55.
    Dependencies 55 [package] name = "hello_world" version= "0.1.0" authors = ["Your Name <you@example.com>”] ! [dependencies] regex = "0.1.41" Cargo.toml lib.rs extern crate regex;
  • 56.
    Modules 56 mod data; mod code; lib.rs/main.rs data/mod.rs modpoint; mod shape; data/point.rs struct Point { } :: data point shape code data/shape/mod.rs struct Point { }
  • 57.
    Often used tomake a mod test for unit tests, or for demonstations. Inline modules 57 mod data { mod point { .. } ! mod shape { .. } } ! mod code { lib.rs/main.rs Exactly the same as creating a separate file.
  • 58.
    Use 58 :: data point shape code code.rs use data::point::Point; data/mod.rs use data::point::Point; useself::point::Point; data/shape.rs use data::point::Point; use super::point::Point;
  • 59.
    Privacy 59 Privacy is thedefault, use pub to override. pub struct Point { pub x: f32, pub y: f32, } impl Point { pub fn m(&self); } pub enum Shape { … } pub mod child; Private means: code in this module or a descendant.
  • 60.
    Where to learnmore 60 doc.rust-lang.org/book users.rust-lang.org / IRC / Stackoverflow doc.rust-lang.org/std
  • 61.