Ben Striegel
@bstrie
A Whirlwind Tour of Rust
SYSTEMS PROGRAMMING FOR THE MODERN DEVELOPER
// C
int sum = 0;
for (int i=0; i<x; i++) {
sum += i;
}
# Python
sum = 0
for i in range(0, x):
sum += i
# `sum()` ist verboten
// Rust
let mut sum = 0;
for i in 0..x {
sum += i;
}
# Ruby
(0...x).inject(0) {|sum, i| sum + i}
# Python
reduce(lambda sum, i: sum + i,
range(0, x), 0)
// Rust
(0..x).fold(0, |sum, i| sum + i)
; Assembly
lea eax, [rdi - 1]
lea ecx, [rdi - 2]
imul rcx, rax
shr rcx
lea eax, [rcx + rdi - 1]
((x - 1) * (x - 2) >> 1) + x - 1
// Rust
(0..x).fold(0, |sum, i| sum + i)
// C, runtime memory error
int* foo() {
int x = 4;
return &x;
}
// Go, safe thanks to GC
func foo() *int {
x := 4
return &x
}
// Rust, does not compile
fn foo() -> &i32 {
let x = 4;
return &x;
}
// Go, with data race
x := 0
for i := 0; i < 10; i++ {
go func() { x += 1 }()
}
// Go, without data race
mutex := &sync.Mutex{}
x := 0
for i := 0; i < 10; i++ {
go func() {
mutex.Lock()
x += 1
mutex.Unlock()
}()
}
// Rust, does not compile
let mut x = 0;
for i in 0..10 {
spawn(|| x += 1);
}
error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function --> race.rs:3:11 | 3 | spawn(|| x += 1); | ^^ - `x` is borrowed here | | | may outlive borrowed value `x`
// Rust
let x = Arc::new(Mutex::new(0));
for i in 0..10 {
let handle = x.clone();
spawn(move || {
*handle.lock().unwrap() += 1;
});
}
// C
void foo() {
int bar = 42;
}
// C
void foo() {
char *ptr = (char*) malloc(42);
free(ptr); // don't forget this!
}
// C
void foo() {
char *ptr1 = (char*) malloc(42);
char *ptr2 = ptr1;
free(ptr1);
free(ptr2); // what happens now?
}
// C
void foo() {
char *ptr1 = (char*) malloc(42);
char *ptr2 = ptr1;
free(ptr1);
char *ptr3 = (char*) malloc(42);
free(ptr2); // what happens now?
}
// Rust
fn foo() {
let ptr1 = String::new();
let ptr2 = ptr1;
}
// Rust
fn foo() {
let ptr1 = String::new();
let ptr2 = ptr1;
let ptr3 = ptr1; // doesn't compile!
}
error[E0382]: use of moved value: `ptr1`
--> src/lib.rs:5:16
|
3 | let ptr1 = String::new();
| ---- move occurs because `ptr1` has type `String`,
| which does not implement the `Copy` trait
4 | let ptr2 = ptr1;
| ---- value moved here
5 | let ptr3 = ptr1;
| ^^^^ value used here after move
// C
void foo() {
int bar = 42;
int qux = bar;
int ham = bar;
}
// Rust
fn foo() {
let foo = 42;
let qux = foo;
let ham = foo;
}
// Rust
fn foo() {
let ptr1 = String::new();
let ptr2 = ptr1;
let ptr3 = ptr1; // doesn't compile!
}
error[E0382]: use of moved value: `ptr1`
--> src/lib.rs:5:16
|
3 | let ptr1 = String::new();
| ---- move occurs because `ptr1` has type `String`,
| which does not implement the `Copy` trait
4 | let ptr2 = ptr1;
| ---- value moved here
5 | let ptr3 = ptr1;
| ^^^^ value used here after move
// C
void foo() {
char *ptr1 = (char*) malloc(42);
char *ptr2 = ptr1;
free(ptr1);
}
// Javascript
function foo() {
let bar = [1, 2, 3];
let qux = bar;
}
// C
void foo() {
char *ptr1 = (char*) malloc(42);
char *ptr2 = ptr1;
// maybe use ptr2 somewhere in here
free(ptr1);
}
// Rust
fn foo() {
let own = String::new();
let borrow = &own; // note the &
}
// Rust
fn foo() {
let own = String::new();
let borrow1 = &own;
let borrow2 = &own;
}
// Rust
fn foo() {
let own = String::new();
let borrow = &own;
borrow.push('x'); // doesn't compile!
}
error[E0596]: cannot borrow `*borrow` as mutable, as it is behind a `&` reference --> src/lib.rs:5:5 | 5 | borrow.push('x'); | ^^^^^^^^^^^^^^^^ `borrow` is a `&` reference, | so the data it refers to | cannot be borrowed as mutable
// Rust
fn foo() {
let mut own = String::new();
let borrow = &mut own;
borrow.push('a');
}
// Rust, doesn't compile
fn foo() {
let mut own = String::new();
let borrow1 = &mut own;
let borrow2 = &mut own;
borrow1.push('a');
}
error[E0499]: cannot borrow `own` as mutable more than once at a time --> src/lib.rs:5:19 | 4 | let borrow1 = &mut own; | -------- first mutable borrow here 5 | let borrow2 = &mut own; | ^^^^^^^^ second mutable borrow here 6 | borrow1.push('a'); | ----------------- first borrow later used here
// Rust, doesn't compile
fn foo() {
let mut vec = Vec::from([1, 2, 3, 4]);
let borrow = &mut vec;
for num in &vec {
borrow.push(num);
}
}
error[E0502]: cannot borrow `vec` as immutable because it is also borrowed as mutable --> src/lib.rs:5:20 | 4 | let borrow = &mut vec; | -------- mutable borrow here 5 | for num in &vec { | ^^^^ immutable borrow here 6 | borrow.push(num); | ---------------- mutable borrow later used here
fn main() {
let greeting = "hello";
println!("{}, world", greeting);
}
struct Point {
x: i32,
y: i32
}
let point = Point { x: 12, y: 34 };
assert!(point.x + point.y == 46);
enum TrafficLight {
Red,
Yellow,
Green
}
let current_light = Green;
match current_light {
Red => println!("Stop!"),
Yellow => println!("Slow down!"),
Green => println!("Go!")
}
let foo = "Hello, world!".find(',');
assert!(foo == Some(5));
let bar = "Hello, world!".find('😎');
assert!(bar == None);
let foo: Result<i32, _> = "42".parse();
assert!(foo == Ok(42));
let bar: Result<i32, _> = "😎".parse();
assert!(bar.is_err());
let foo: i32 = "42".parse()?;
// Equivalent to:
let foo: i32 = match "42".parse() {
Ok(num) => num,
Err(e) => return Err(e)
};
// this works:
let foo;
if some_array.is_empty() {
foo = "that array is empty!";
} else {
foo = "no, it ain't!";
}
// or equivalently:
let foo = if some_array.is_empty() {
"that array is empty!"
} else {
"no, it ain't!"
};
struct Point { x: i32, y: i32 }
impl Point {
fn new(x: i32, y: i32) -> Self {
Point { x, y }
}
fn add_those_coords(&self) -> i32 {
self.x + self.y
}
}
let point = Point::new(12, 34);
assert!(point.add_those_coords() == 46);
trait PointTrait {
fn new(x: i32, y: i32) -> Self;
fn add_those_coords(&self) -> i32;
}
impl PointTrait for Point {
fn new(x: i32, y: i32) -> Self {
Point { x, y }
}
fn add_those_coords(&self) -> i32 {
self.x + self.y
}
}
www.rust-lang.org
Whirlwind Tour of Rust
By bstrie
Whirlwind Tour of Rust
- 242