Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
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...
My god, it’s full of bugs
3
Dangling pointers
!
Segmentation faults
!
Double frees
!
Uninitialized data
!
Null pointer exc...
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...
Assembly code
6
leaq (%rdi,%rsi,4), %rcx
xorl %eax, %eax
jmp .LBB5_1
.LBB5_3:
addl %edx, %eax
.align 16, 0x90
.LBB5_1:
cmp...
fn foo(v: &Vec<i32>) -> i32 {
v.iter()
.filter(|i| **i > 0)
.map(|i| *i)
.sum()
}
Higher-level coding
7
…generates the sam...
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...
Parallel
9
use std::thread;
fn qsort(data: &mut [i32])
if data.len() <= 1 {
return;
}
let mid = partition(data[0], data);
...
Open and welcoming
Rust has been open source from the beginning.
!
Open governance model based on public RFCs.
!
We have a...
Getting Started
11
You can either install Rust, or
just use play.rust-lang.org
Exercises are available at:
!
http://nikoma...
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...
The Big Idea
Ownership and borrowing:!
!
1. All memory has a clear owner.
2. Others can borrow from the owner.
3. Owner ca...
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...
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
…
}
vec.push(2);
Compiler enforces moves
fn tak...
void give() {
Vector vec = …;
vec.add(1);
vec.add(2);
take(vec);
vec.add(3);
}
void take(Vector vec) {
// …
}
!
!
!
“Owner...
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] = su...
Clone
22
fn main() {
let d = vec![1, 3, 4, 10];
let ps = prefix_sum(d);
println!("prefix sum of {:?} is {:?}",
d, ps);
}
h...
Clone
23
fn main() {
let d = vec![1, 3, 4, 10];
let ps = prefix_sum(d.clone());
println!("prefix sum of {:?} is {:?}",
d, ...
24
struct Point {
x: u32,
y: u32
}
!
fn area(ul: Point, lr: Point) -> u32 {
(lr.x - ul.x) * (lr.y - ul.y)
}
!
fn main() {
...
“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 t...
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...
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, ...
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...
fn example() {
let mut names = Vec::new();
names.push(..);
names.push(..);
let name = &names[1];
names.push(..);
print(nam...
Rust solution
34
Compile-time read-write-lock:!
!
Creating a shared reference to X “read locks” X.
- Other readers OK.
- N...
fn example() {
let mut names = Vec::new();
names.push(“brson”);
names.push(“pcwalton”);
let name = &names[1];
names.push(“...
Outside of borrow scope — OK.
Scope of borrow
in this case covers
only the loop body.
36
http://is.gd/thMY5N
fn main() {
l...
Rust reasons about scopes
37
fn main() {
let mut names = Vec::new();
names.push("brson");
names.push("pcwalton");
for i in...
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(&sel...
Common derivations
41
#[derive(PartialEq)]
+ #[derive(PartialOrd)]
#[derive(Clone)]
#[derive(Debug)]
x == y, x != y
x < y,...
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 Sha...
const PI: f32 = 3.14159;
impl Shape {
fn area(&self) -> f32 {
match *self {
Shape::Circle { origin: _, radius: r } =>
PI *...
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 colo...
47
struct Shape {
color: Option<Color>
}
!
impl Shape {
fn new() -> Shape {
Shape { color: None }
}
!
fn get_color(&self, ...
48
match self.color {
None => default,
Some(ref c) => c.clone()
}
if let Some(ref c) = self.color {
c.clone()
} else {
def...
Slices
49
fn main() {
// Heap-allocated.
let v: Vec<i32> = vec![1, 2, 3, 4];
!
// Reference to one element.
let e: &i32 = ...
Mutable slices
50
fn main() {
// Heap-allocated.
let mut v: Vec<i32> = vec![1, 2, 3, 4];
println!(“v={:?}”, v);
{
let slic...
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 &...
Iterators
52
struct PlayerScore {
player_name: String,
score: u32
}
!
fn high_scorers(v: Vec<PlayerScore>)
-> Vec<(String,...
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:
...
Dependencies
55
[package]
name = "hello_world"
version = "0.1.0"
authors = ["Your Name <you@example.com>”]
!
[dependencies...
Modules
56
mod data;
mod code;
lib.rs/main.rs
data/mod.rs
mod point;
mod shape;
data/point.rs
struct Point {
}
::
data
poi...
Often used to make
a mod test for unit tests,
or for demonstations.
Inline modules
57
mod data {
mod point {
..
}
!
mod sh...
Use
58
::
data
point
shape
code
code.rs
use data::point::Point;
data/mod.rs
use data::point::Point;
use self::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...
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!
Upcoming SlideShare
Loading in …5
×

Rust tutorial from Boston Meetup 2015-07-22

702 views

Published on

A tutorial on Rust given at the Boston Meetup on 2015-07-22

Published in: Software
  • Be the first to comment

Rust tutorial from Boston Meetup 2015-07-22

  1. 1. Nicholas Matsakis! Mozilla Research
  2. 2. 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 :)
  3. 3. 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. 4. 4 Systems programming without the hassle crashes! heisenbugs! fear Parallel!
  5. 5. // 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.
  6. 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. 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. 8. 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.
  9. 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. 10. 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
  11. 11. 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/
  12. 12. Outline 12 1. The big ideas:! a. Ownership b. Borrowing 2. Everyday life:! a. Data types b. Modules and privacy c. Cargo
  13. 13. Ownership! ! n. The act, state, or right of possessing something. 13 Borrow! ! v. To receive something with the promise of returning it.
  14. 14. 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
  15. 15. Ownership/Borrowing Memory safety Data-race freedom No need for a runtime GCC++ 15
  16. 16. Clean up the mess 16 http://mylifeandkids.com/messy-house-edition-boys-bedroom-2/
  17. 17. Ownership 17
  18. 18. 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
  19. 19. 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
  20. 20. 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
  21. 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. 22. 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
  23. 23. 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. 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. 25. “Copy” types 25 #[derive(Copy, Clone)] struct Point { x: u32, y: u32 }
  26. 26. 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. 27. 27 Exercise #1.
  28. 28. * Actually: mutation only in controlled circumstances * Shared borrow (&T) Sharing Mutation
  29. 29. Mutable borrow (&mut T) 29 Sharing Mutation
  30. 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. 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. 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
  33. 33. 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
  34. 34. 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.
  35. 35. 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
  36. 36. 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"); }
  37. 37. 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
  38. 38. Take a break. 38
  39. 39. Daily life in Rust 39
  40. 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. 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. 42. Enums 42 struct Point {..} ! enum Shape { Circle { origin: Point, radius: f32 }, ! Rectangle { ul: Point, lr: Point } }
  43. 43. 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 } } }
  44. 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. 45. Option 45 enum Option<T> { None, Some(T), }
  46. 46. No null types 46 class Shape { Color color; ! Shape() { } ! Color getColor(Color default) { if (color != null) return color; return default; } } (Java)
  47. 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. 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. 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. 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. 51. 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
  52. 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. 53. Programming in the large 53
  54. 54. 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
  55. 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. 56. 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 { }
  57. 57. 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.
  58. 58. 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;
  59. 59. 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.
  60. 60. Where to learn more 60 doc.rust-lang.org/book users.rust-lang.org / IRC / Stackoverflow doc.rust-lang.org/std
  61. 61. 61 Thanks for listening!

×