Me

NN ➡️ Helsinki ➡️ Singapore ➡️ Tokyo

Social: Github, Twitter

C, Python, Scala

Interests: Functional Programming, Computer Graphics (GLSL), Programming Languages & PL design

  • Rust
  • Julia
  • Unison * 1 2
  • J 1

History

2010 Pet project by Graydon Hoare at Mozilla Research

2015 Hits 1.0

2016 Firefox Quantum

2018 Rust 👀 Me

Bullet points

  • Strong static typing 1
  • Type inference
  • No GC
  • No exceptions
  • No null's *
  • Memory safety *
fn main() {
  let a = vec![1, 2, 3, 4, 5];
  println!("{:?}", a);

  let sum: u32 = a.iter().sum();
  println!("{}", sum);
}

Ownership & Borrowing

  • T - owned value of type T
  • &T - reference to value of type T
fn sum(a: &Vec<u32>) -> u32 {
  a.iter().sum()
}

fn add_one(a: Vec<u32>) -> Vec<u32> {
  a.into_iter().map(|e| e + 1).collect()
}

fn main() {
  let a = vec![1, 2, 3, 4, 5];

  println!("{}", sum(&a));
  println!("{:?}", add_one(a));
}

Mutation | Aliasing

  • &mut T - unique reference to value of type T
  • many &T or one &mut T at the same time
fn add_one_inplace(a: &mut Vec<u32>) {
  for e in a.iter_mut() {
    *e += 1;
  }
}

fn main() {
  let mut a = vec![1, 2, 3, 4, 5];
  println!("{:?}", a);

  for _ in 0..3 {
    add_one_inplace(&mut a);
  }
  println!("{:?}", a);
}

Example: Mutex

In imaginary game engine

class Posion:
  def onTick(self):
    self.entity.health -= 1

class Missile:
  def onCollide(self, entity):
    with entity.lock():
      entity.health -= 10

In Rust Mutex owns its underlying data

use std::sync::Mutex;

fn main() {
  let entity: u32 = 0;
  let e = Mutex::new(entity);
  e.lock();
}

Source: RustConf 2021 Compile-Time Social Coordination 1

Structs & Impls

struct Point {
  x: f32,
  y: f32,
}

impl Point {
  fn distance(&self, other: &Point) -> f32 {
    ((self.x - other.x).powf(2.) + (self.y - other.y).powf(2.)).sqrt()
  }

  fn shift(&mut self, x: f32, y: f32) {
     self.x += x;
     self.y += y;
  }
}

fn main() {
  let origin = Point { x: 0., y: 0. };
  let mut p1 = Point { x: 0., y: 2. };
  println!("distance {}", origin.distance(&p1));
  p1.shift(5., -2.);
  println!("distance {}", origin.distance(&p1));
}

Algebraic Data Types & Pattern Matching

  • product types as structs 1
  • sum types as enums 1
enum Option<T> {
  None,
  Some(T),
}

fn test(values: Option<&Vec<u32>>) -> String {
  match values {
    Option::None =>
      "none".to_string(),
    Option::Some(v) if v.len() > 3 =>
      "3+".to_string(),
    Option::Some(v) =>
      v.len().to_string(),
  }
}

fn main() {
  let v = vec![1, 2, 3, 4];
  println!("{}", test(Option::Some(&v)));
}

Manual Memory

Types need to have known size

enum List<T> {
  Nil,
  Cons(T, Box<List<T>>),
}

fn main() {}
  • Box is a heap pointer 1
  • Box pointer is never null
  • Box pointer gets deallocated when the handle goes out of scope

Other kinds of managed pointers 1

Manual Memory

It gets worse

use std::rc::Rc;
use std::cell::RefCell;

type Link<T> = Rc<RefCell<Node<T>>>;

struct Node<T> {
  data: T,
  next: Option<Link<T>>,
  previous: Option<Link<T>>,
}

fn main() {}
  • Rc is reference counting pointer 1
  • copying Rc increments counter
  • when Rc handle goes out of scope it decrements counter
  • RefCell is a type that allows interior mutability 1

Too Many Linked Lists 1

Traits

  • No inheritance
  • Behavior described through traits
struct Point {
  x: f32,
  y: f32,
}

trait Show {
  fn show(&self) -> String;
}

impl Show for Point {
  fn show(&self) -> String {
    format!("{};{}", self.x, self.y)
  }
}

fn main() {
  let p = Point { x: 0.5, y: 1.3 };
  println!("{}", p.show());
}

Parameter polymorphism

Add guards to generic arguments to describe fine-grained behavior

trait Show {
  fn show(&self) -> String;
}

enum List<T> {
  Nil,
  Cons(T, Box<List<T>>),
}

impl<T: Show> Show for List<T> {
  fn show(&self) -> String {
    match self {
      List::Nil => "Nil".to_string(),
      List::Cons(t, l) => format!("{} -> {}", t.show(), l.show())
    }
  }
}

impl Show for u32 {
  fn show(&self) -> String { self.to_string() }
}

fn main() {
  let l = List::Cons(10, Box::new(List::Cons(5, Box::new(List::Nil))));
  println!("{}", l.show());
}

For dynamic dispatch see also chapter on trait objects 1

stm32

Blue Pill: stm32f103c8t6

  • ARM Cortex-M3
  • 32 bit, 1-core
  • 72 Mhz clock
  • 64 KB FLASH
  • 20 KB RAM

Demos: stm32

Libraries & Tools

WebAssembly

  • Binary executable format
  • Supported by all major browsers
  • Linear memory

Rust

Demos: WASM

Conway's Game of Life

Simple Sandbox Simulation

Simplex Noise Procedural Generation

Notable features

Most references from The Rust Book

How to get started

Install rustup

Check out the book

Check out the book on WebAssebmly

Place to find libraries

Some community resources

Projects

Stories

  • Discord cache service 1
  • ScyllaDB driver (implementation of Cassandra) 1
  • Google Security: Android Kernel 1
  • Dropbox Capture 1
  • Linux Kernel patches to make Rust availiable for contribution 1

Thank you