rust intro
TRANSCRIPT
![Page 1: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/1.jpg)
Rust Intro
by Artur Gavkaliuk
![Page 2: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/2.jpg)
MozillaThe language grew out of a personal project by Mozilla employee Graydon Hoare. Mozilla began sponsoring the project in 2009 and announced it in 2010. The same year, work shifted from the initial compiler (written in OCaml) to the self-hosting compiler written in Rust. Known as rustc, it successfully compiled itself in 2011. rustc uses LLVM as its back end.
![Page 3: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/3.jpg)
Safe, concurrent, practical languageRust is a general-purpose, multi-paradigm, compiled programming language.
It is designed to be a "safe, concurrent, practical language", supporting pure-functional, imperative-procedural, and object-oriented styles.
![Page 4: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/4.jpg)
Object oriented
Structs
Enums
Method Syntax
Generics
Traits
![Page 5: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/5.jpg)
Structsstruct Point { x: i32, y: i32,}
fn main() { let origin = Point { x: 0, y: 0 }; // origin: Point
println!("The origin is at ({}, {})", origin.x, origin.y);}
![Page 6: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/6.jpg)
Enumsenum BoardGameTurn { Move { squares: i32 }, Pass,}
let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 };
![Page 7: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/7.jpg)
Genericsstruct Point<T> { x: T, y: T,}
let int_origin = Point { x: 0, y: 0 };let float_origin = Point { x: 0.0, y: 0.0 };
![Page 8: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/8.jpg)
Method syntaxstruct Circle { x: f64, y: f64, radius: f64,}
fn main() { let c = Circle { x: 0.0, y: 0.0, radius: 2.0 }; println!("{}", c.area());}
![Page 9: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/9.jpg)
Method syntaximpl Circle { fn area(&self) -> f64 { std::f64::consts::PI * (self.radius * self.radius) }}
![Page 10: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/10.jpg)
Traitstrait HasArea { fn area(&self) -> f64;}
impl HasArea for Circle { fn area(&self) -> f64 { std::f64::consts::PI * (self.radius * self.radius) }}
![Page 11: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/11.jpg)
Traitsfn print_area<T: HasArea>(shape: T) { println!("This shape has an area of {}", shape.area());}
![Page 12: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/12.jpg)
Functional
Functions
Function pointers
Type inference
Immutable by default
Option and Result
Pattern matching
Lambda functions
![Page 13: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/13.jpg)
Functionsfn add_one(x: i32) -> i32 { x + 1}
![Page 14: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/14.jpg)
Functionsfn add_one(x: i32) -> i32 { x + 1;}
We would get an error:
error: not all control paths return a valuefn add_one(x: i32) -> i32 { x + 1;}
help: consider removing this semicolon: x + 1; ^
![Page 15: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/15.jpg)
Functionsfn plus_one(i: i32) -> i32 { i + 1}
let f: fn(i32) -> i32 = plus_one;
let six = f(5);
![Page 16: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/16.jpg)
Type inference
Rust has this thing called ‘type inference’. If it can figure out what the type of something is, Rust doesn’t require you to actually type it out.
let x = 5; // x: i32
fn plus_one(i: i32) -> i32 { i + 1}
// without type inferencelet f: fn(i32) -> i32 = plus_one;
// with type inferencelet f = plus_one;
![Page 17: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/17.jpg)
Mutabilitylet x = 5;x = 10;
error: re-assignment of immutable variable `x` x = 10; ^~~~~~~
![Page 18: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/18.jpg)
Mutabilitylet mut x = 5; // mut x: i32x = 10;
![Page 19: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/19.jpg)
Optionpub enum Option<T> { None, Some(T),}
![Page 20: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/20.jpg)
Option
fn divide(numerator: f64, denominator: f64) -> Option<f64> { if denominator == 0.0 { None } else { Some(numerator / denominator) }}
![Page 21: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/21.jpg)
Result
enum Result<T, E> { Ok(T), Err(E)}
![Page 22: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/22.jpg)
fn divide(numerator: f64, denominator: f64) -> Result<f64, &'static str> { if denominator == 0.0 { Err("Can not divide by zero") } else { Ok(numerator / denominator) }}
Result
![Page 23: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/23.jpg)
Pattern matchinglet x = 5;
match x { 1 => println!("one"), 2 => println!("two"), 3 => println!("three"), 4 => println!("four"), 5 => println!("five"), _ => println!("something else"),}
![Page 24: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/24.jpg)
Pattern matching
One of the many advantages of match is it enforces ‘exhaustiveness checking’. For example if we remove the last arm with the underscore _, the compiler will give us an error:
error: non-exhaustive patterns: `_` not covered
![Page 25: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/25.jpg)
Pattern matching
// The return value of the function is an optionlet result = divide(2.0, 3.0);
// Pattern match to retrieve the valuematch result { // The division was valid Some(x) => println!("Result: {}", x), // The division was invalid None => println!("Cannot divide by 0"),}
![Page 26: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/26.jpg)
Pattern matching
// The return value of the function is an Result<f64, &'static str>let result = divide(2.0, 3.0);
// Pattern match to retrieve the valuematch result { // The division was valid Ok(x) => println!("Result: {}", x), // The division was invalid Err(e) => println!(e),}
![Page 27: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/27.jpg)
Pattern matching
Again, the Rust compiler checks exhaustiveness, so it demands that you have a match arm for every variant of the enum. If you leave one off, it will give you a compile-time error unless you use _ or provide all possible arms.
![Page 28: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/28.jpg)
Lambda functionslet plus_one = |x: i32| x + 1;
assert_eq!(2, plus_one(1));
![Page 29: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/29.jpg)
Closureslet num = 5;let plus_num = |x: i32| x + num;
assert_eq!(10, plus_num(5));
![Page 30: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/30.jpg)
Function pointersfn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 { some_closure(1)}
fn add_one(i: i32) -> i32 { i + 1}
let f = add_one;
let answer = call_with_one(&f);
assert_eq!(2, answer);
![Page 31: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/31.jpg)
Memory Safe
The Stack and the Heap
Ownership
Borrowing
Lifetimes
![Page 32: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/32.jpg)
The Stackfn foo() { let y = 5; let z = 100;}
fn main() { let x = 42;
foo();}
![Page 33: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/33.jpg)
The Stackfn foo() { let y = 5; let z = 100;}
fn main() { let x = 42; <-
foo();}
Address Name Value
0 x 42
![Page 34: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/34.jpg)
The Stackfn foo() { let y = 5; let z = 100;}
fn main() { let x = 42;
foo(); <-}
Address Name Value
2 z 1000
1 y 5
0 x 42
![Page 35: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/35.jpg)
The Stackfn foo() { let y = 5; let z = 100;}
fn main() { let x = 42;
foo();} <-
Address Name Value
0 x 42
![Page 36: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/36.jpg)
The Heapfn main() { let x = Box::new(5); let y = 42;}
Address Name Value
(230) - 1 5
... ... ...
1 y 42
0 x → (230) - 1
![Page 37: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/37.jpg)
Ownershiplet v = vec![1, 2, 3];
let v2 = v;
println!("v[0] is: {}", v[0]);
error: use of moved value: `v`println!("v[0] is: {}", v[0]); ^
![Page 38: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/38.jpg)
Ownershipfn take(v: Vec<i32>) { // what happens here isn’t important.}
let v = vec![1, 2, 3];
take(v);
println!("v[0] is: {}", v[0]);
Same error: ‘use of moved value’.
![Page 39: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/39.jpg)
Borrowingfn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) { // do stuff with v1 and v2
// hand back ownership, and the result of our function (v1, v2, 42)}
let v1 = vec![1, 2, 3];let v2 = vec![1, 2, 3];
let (v1, v2, answer) = foo(v1, v2);
![Page 40: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/40.jpg)
Borrowingfn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 { // do stuff with v1 and v2
// return the answer 42}
let v1 = vec![1, 2, 3];let v2 = vec![1, 2, 3];
let answer = foo(&v1, &v2);
// we can use v1 and v2 here!
![Page 41: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/41.jpg)
&mut referencesfn foo(v: &Vec<i32>) { v.push(5);}
let v = vec![];
foo(&v);
errors with:
error: cannot borrow immutable borrowed content `*v` as mutablev.push(5);^
![Page 42: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/42.jpg)
&mut referencesfn foo(v: &mut Vec<i32>) { v.push(5);}
let mut v = vec![];
foo(&mut v);
![Page 43: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/43.jpg)
The Rules
First, any borrow must last for a scope no greater than that of the owner. Second, you may have one or the other of these two kinds of borrows, but not both at the same time:
one or more references (&T) to a resource,
exactly one mutable reference (&mut T).
![Page 44: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/44.jpg)
Rust prevents data races at compile time
There is a ‘data race’ when two or more pointers access the same memory location at the same time, where at least one of them is writing, and the operations are not synchronized.
![Page 45: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/45.jpg)
Lifetimes
1. I acquire a handle to some kind of resource.
2. I lend you a reference to the resource.
3. I decide I’m done with the resource, and deallocate it, while you still have your reference.
4. You decide to use the resource.
![Page 46: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/46.jpg)
Lifetimes// implicitfn foo(x: &i32) {}
// explicitfn bar<'a>(x: &'a i32) {}
![Page 47: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/47.jpg)
Lifetimes
You’ll also need explicit lifetimes when working with structs that contain references.
![Page 48: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/48.jpg)
Lifetimesstruct Foo<'a> { x: &'a i32,}
fn main() { let y = &5; // this is the same as `let _y = 5; let y = &_y;` let f = Foo { x: y };
println!("{}", f.x);}
![Page 49: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/49.jpg)
Lifetimes
We need to ensure that any reference to a Foo cannot outlive the reference to an i32 it contains.
![Page 50: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/50.jpg)
Thinking in scopesfn main() { let y = &5; // -+ y goes into scope // | // stuff // | // |} // -+ y goes out of scope
![Page 51: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/51.jpg)
Thinking in scopesstruct Foo<'a> { x: &'a i32,}
fn main() { let y = &5; // -+ y goes into scope let f = Foo { x: y }; // -+ f goes into scope // stuff // | // |} // -+ f and y go out of scope
![Page 52: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/52.jpg)
Thinking in scopesstruct Foo<'a> { x: &'a i32,}
fn main() { let x; // -+ x goes into scope // | { // | let y = &5; // ---+ y goes into scope let f = Foo { x: y }; // ---+ f goes into scope x = &f.x; // | | error here } // ---+ f and y go out of scope // | println!("{}", x); // |} // -+ x goes out of scope
![Page 53: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/53.jpg)
Not Covered
Macros
Tests
Concurrency
Foreign Function Interface
Cargo
and much much more
![Page 54: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/54.jpg)
Resources
The Rust Programming Language. Also known as “The Book”, The Rust Programming Language is the
most comprehensive resource for all topics related to Rust, and is the primary official document of the
language.
Rust by Example. A collection of self-contained Rust examples on a variety of topics, executable in-
browser.
Frequently asked questions.
The Rustonomicon. An entire book dedicated to explaining how to write unsafe Rust code. It is for
advanced Rust programmers.
rust-learning. A community-maintained collection of resources for learning Rust.
![Page 55: Rust Intro](https://reader036.vdocuments.us/reader036/viewer/2022070512/589c95b11a28ab1e5d8b6f5d/html5/thumbnails/55.jpg)
Thank You!