Rust Beginners Workshop

09:30Doors open.
Install rust-up & stable Rust.
See https://www.rustup.rs
10:001. Intro to Rust
10:30Break
10:452. Ownership & the Borrow Checker
11:15Break
11:303. Traits
12:00Break
12:15Explaining Assignment
12:45LUNCH BREAK
14:00Working on assignment
17:30Wrapping up & Clean-up
18:00Venue closes

Welcome!

Please install rust stable (via https://www.rustup.rs/)

WiFi: CS Guest. No pwd needed ;)

Me

Maarten Hoogendoorn

  • Twitter @moretea_nl
  • GitHub @moretea
  • Work @ Container Solutions (we're hiring)
  • Run Nix & Rust Meetup

today

make you dangerous

ask questions!

A story in three parts

  1. Getting Started & Basics
  2. Safety
  3. Fancy stuff

assignment

part I

  • Installing Rust
  • Creating a Hello World project
  • Basics of the language
  • Organizing stuff
  • External dependencies

Installing stuff

Rust release process

  • Release trains
  • nightly, beta, stable

rustup

https://rustup.rs/

install me a rust

  • rustup install stable
  • rustup update
    (if installed rust before)

Create project


$ cargo
Usage:
  cargo <command> [<args>...]
  cargo [options]

Options:
  -h, --help          Display this message
  ...

Some common cargo commands are (see all commands with --list):
  build       Compile the current project
  new         Create a new cargo project
  run         Build and execute src/main.rs
  ...

See 'cargo help <command>' or more information on a specific command.

$ cargo new -h
Create a new cargo package at <path>

Usage:
    cargo new [options] <path>
    cargo new -h | --help

Options:
    -h, --help          Print this message
    --vcs VCS           Initialize a new repository for the given version
                        control system (git or hg) or do not initialize any version
                        control at all (none) overriding a global configuration.
    --bin               Use a binary (application) template
    --lib               Use a library template
    --name NAME         Set the resulting package name
    -v, --verbose ...   Use verbose output
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date
            

hello world


$ cargo new --bin hello_world
Created binary (application) `hello_world` project
            

$ cd hello_world
$ find | grep -v git
.
./Cargo.toml
./src
./src/main.rs
            

$ cat ./src/main.rs 
fn main() {
    println!("Hello, world!");
}
            

$ cargo run
Compiling hello_world v0.1.0 (file:///home/maarten/community/rust-meetup/workshop/slides/01-code/hello_world)
 Finished debug [unoptimized + debuginfo] target(s) in 0.45 secs
  Running `target/debug/hello_world`
Hello, world!
            

Simple types


fn main() {
  let x : bool = true;
  println!("Is it {}?", x);
}
            

fn main() {
  let x = true;
  println!("Is it {}?", x);
}
            

fn main() {
  let x = true;
  x = false;
  println!("Is it {}?", x);
}
            

error[E0384]: re-assignment of immutable variable `x`
 --> <anon>:3:5
  |
2 |     let x = true;
  |         - first assignment to `x`
3 |     x = false;
  |     ^^^^^^^^^ re-assignment of immutable variable

error: aborting due to previous error
            

fn main() {
  let mut x : bool = true;
  x = false;
  println!("Is it {}?", x);
}
            

fn main() {
  let x : String = "my_string".to_string();
  let y : 'static str = "my other string";
}
            

fn main() {
  let x : u64 = 64;
  let y : u8 = 300; 
}
            

warning: literal out of range for u8, #[warn(overflowing_literals)] on by default
            

Unit


fn main() {
  let x = ();
  println!("Hello, world! {:?}", x);
}
            

Hello, world! ()
            

if


fn main() {
  let x = true;

  if x {
    println!("JEP!");
  } else {
    println!("NOPE");
  }
}
            

Compound types

Tuple


fn main() {
  let x = (1, "cool");
  let y: (u8, &'static str) = (1, "cool");

  println!("first: {:?}, second: {:?}", x.0, x.1);
}
            

Struct


struct Person {
  name: String,
  age: u8
}

fn main() {
  let maarten = Person { 
    name: "Maarten".to_string(), 
    age: 29
  };
}
            

Struct - derive


#[derive(Debug)]
struct Person {
  name: String,
  age: u8
}

fn main() {
  let maarten = Person { 
    name: "Maarten".to_string(), 
    age: 28 
  };
  println!("{:?}", &maarten);
}
            

Enum


#[derive(Debug)]
struct StateOfMind {
  Happy,
  Meh(String)
}

fn main() {
  let x = StateOfMind::Happy;
  let y = StateOfMind::Meh("reason".to_string());
}
            

Enum - match


#[derive(Debug)]
enum StateOfMind {
  Happy,
  Meh(String)
}

fn main() {
  let x = StateOfMind::Happy;
  let y = StateOfMind::Meh("reason".to_string());

  let z = x;

  match z {
    StateOfMind::Happy => println!("Happy!"),
    StateOfMind::Meh(why) =>
      println!("Not happy :( {:?}", why)
  }
}
            

functions


fn some_function() {
  // ...
}
            

fn some_function() -> u64 {
  return 42;
}
            

fn some_function() -> u64 {
  42
}
            

closures


fn main() {
  let to_add = |x, y| x + y;
  println!("{}", to_add(1,2));
}
            

Generics


#[derive(Debug)]
pub stuct Nameable<T> {
    name: String,
    thing: T
}

fn main() {
    let x : Nameable<u64> = Nameable { 
      name: "a u64".into(),
      thing: 42
    };
    println!("Hello, world! {:?}", x);
}
            

Rust has no null


pub enum Option<T> {
    None,
    Some(T),
}
            

Rust has no exceptions


pub enum Result<T, E> {
    Ok(T),
    Err(E),
}
            

std

standard library

Useful containers

Vec

HashMap

Organization of code

module

mod my_mod {
    struct Thing;
}

fn main() {
    let x = my_mod::Thing;
}
            

play

import modules

live coding

crates

  • Batteries included (Python, Ruby)
  • Ecosystem of libs (Node, Java, Rust)

Demo to generate random number

  • crates.io
  • Add crate to project

break!

Break!

Traits

a bit like interfaces

trait Age {
  fn description(&self) -> String;
}

impl Age for u64 {
  fn description(&self) -> String {
    format!("{} years old", &self)
  }
}

struct Person {
    name: String,
    age: u64
}

impl Age for Person {
    fn description(&self) -> String {
        format!("{} is {} years old", self.name, self.age)
    }
}

fn main () {
    let x : u64 = 42;

    println!("{}", x.description());

    let m = Person {
        name: "Maarten".to_string(),
        age: 28
    };

    println!("{}", m.description());
}
            

42 years old
Maarten is 28 years old
            

impl without trait


pub struct Person {
    first_name: String,
    last_name: String
}

impl Person {
    fn full_name(&self) -> String {
        format!("{} {}", self.first_name, self.last_name)
    }
}

fn main() {
    let maarten = Person { first_name: "Maarten".into(), last_name: "Hoogendoorn".into() };
    println!("Person: {}", maarten.full_name())
}
            

impl without trait in std

Traits in std & Ecosystem

example of iterating over Vec

Special Traits

Hack

  • http://rustbyexample.com
  • Challenge 1: Fruit Voting
  • Challenge 2: Regexp matching

Challenge 1

  • Read CSV file
  • 
    apple, 2
    banana, 2
    orange, 5
    banana, 10
    orange, 5
    ...
                    
  • Sums votes for all fruits + sort

hints

  • API documentation
  • HashMap

Challenge 2

Regular Expression Evaluator