about Rust

Who am I?

Geoffroy Couprie

Freelance in software security

VLC developer

Running the Scala.IO WiFi

About Rust

History

Goals

problems with C?

memory errors

pointer arithmetic

Why not Haskell?

Close to the metal

No surprises

Mutability

let a = 1;     // immutable by default
let mut b = 2; // declare mutability

Easy pattern

Keep mutability inside a function scope

fn fillStrings() -> ~[~str] {
  let mut strings:~[~str] = ~[];
  strings.push("hello");
  strings.push("world");
  strings
}

Data types

struct Point {
  x: float,
  y: float
}

enum Shape {
  Circle(Point, float),
  Rectangle(Point, Point)
}

let mytup2: (int, int, float) = (10, 20, 30.0);
// VS
struct MyTup(int, int, float);
let mytup: MyTup = MyTup(10, 20, 30.0);

Enumerations

enum Color {
  Red,
  Green,
  Blue
}
fn f(c: Color) {
  match c {
    Red   => // ...
    Green => // ...
    Blue  => // ...
  }
}

Pattern matching

fn f(c: Color) {
  match c {
    Red   => // ...
    Green => // ...
  }
}

-> error: non-exhaustive patterns: Blue not covered
fn f(c: Color) {
  match c {
    Red   => // ...
    Green => // ...
    Blue  => // ...
    1     => // ...
  }
}

-> error: mismatched types: expected `Color` but found `<VI0>`
(expected enum Color but found integral variable)

Closures and loops

fn apply(i: int, f: fn(int) -> int) -> int {
  f(i)
}

apply(4, |x| { x * x });

//////

for range(0, 10) |i| {
  println!("number: {}", i);
}
//expands to
range(0, 10, |i| {
  println!("number: {}", i);
}
// or you can do
let mut j = 0;
while(j < 10) {
  println!("number: {}", i);
  j += 1;
}

No Tail call optimization

Methods

struct Pair { first: int, second: int };

impl Pair {
  fn product(&self) -> int {
    self.first * self.second
  }
}

let p:Pair = Pair(1, 2);
let a:int  = p.product();

Generics

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

Nice, but not enough

Traits

trait Printable {
  fn print(&self);
}

impl Printable for int {
  fn print(&self) { println(fmt!("%d", *self)) }
}

impl Printable for ~str {
  fn print(&self) { println(*self) }
}

// static dispatch
fn print_whatever<T: Printable>(things: ~[T]) {
  for element in things.iter() { element.print(); }
}

// dynamic dispatch
fn print_dynamic(things: ~[@Printable]) {
  for element in things.iter() { element.print(); }
}

Ok, that was easy

Let's talk about memory

Memory storage

Storage:

let on_the_stack      : Pair  = Pair(1, 2);

let on_the_heap       : ~Pair = ~Pair(1, 2);

let garbage_collected : @Pair = @Pair(1, 2); // deprecated

Pointer types:

Great for concurrency

Tasks

let (port, chan): (Port<int>, Chan<int>) = stream();

do spawn || {
    let result = some_expensive_computation();
    chan.send(result);
}

some_other_expensive_computation();
let result = port.recv();

Also: macros, FFI, UTF-8, bits...

Moving target

Usage

When you need safety

When you need performance

When you go native

http://www.rust-lang.org/

#rust on irc.mozilla.org

http://www.reddit.com/r/rust