a-rusty-introduction



a-rusty-introduction

0 0


a-rusty-introduction

A gentle hello to the `rust` programming language

On Github mletterle / a-rusty-introduction

A Rusty Introduction

a gentle hello to the rust programming language

by Michael Letterle

Rust is Like C

fn main() {
    println("Hello, rustics!");
}

But

  • Safe
  • Concurrent
  • Practical

Safe

  • No null pointers
  • Default immutability
  • No shared mutable state

No null pointers

Unlike C there is no way to dereference a null pointer.

fn main() {
    let x = (); // the unit type, also called nil, is the closest you can get to null
    println(x.to_str());
}

Default immutability

fn main() {
   let x = 1;
   x = 2;
   println(x.to_str());
}
$ rustc immutable.rs
immutable.rs:3:4: 3:5 error: re-assignment of immutable variable `x`
immutable.rs:3     x = 2;
                   ^
immutable.rs:2:8: 2:9 note: prior assignment occurs here
immutable.rs:2     let x = 1; 
                       ^
error: aborting due to previous error

Default immutability

fn main() {
   let mut x = 1;
   x = 2;
   println(x.to_str());
}
$ rustc mutable.rs
mutable.rs:2:8: 2:13 warning: value assigned to `x` is never read,
                            #[warn(dead_assignment)] on by default
mutable.rs:2     let mut x = 1; 
                  ^~~~~
$ ./mutable
2

No shared mutable state

fn main() {
    for num in range(0, 5) {
        let mut x = 1; 
        do spawn {
            x = x + num;
            println(format!("{}", x));
       }
    }
}
$ rustc shared.rs
shared.rs:5:12: 5:13 error: cannot assign to immutable captured outer variable in a heap closure
shared.rs:5             x = x + num;
                        ^
shared.rs:5:16: 5:17 error: mutable variables cannot be implicitly captured
shared.rs:5             x = x + num;
                            ^
error: aborting due to 2 previous errors

No shared mutable state

fn main() {
    for num in range(0, 5) {
        let x = 1; 
        do spawn {
            println(format!("{}", x + num));
       }
    }
}
$ rustc shared.rs
$ ./shared
4
5
2
1
3

Concurrent

  • Lightweight tasks
  • No shared mutable state
  • Fast asynchronus messaging

Lightweight tasks

No shared mutable state

We saw this previously:

fn main() {
    for num in range(0, 5) {
        let x = 1; 
        do spawn {
            println(format!("{}", x + num));
       }
    }
}

Fast asynchronus messaging

extern mod extra;
use extra::comm::DuplexStream;

fn do_task(channel: &DuplexStream<int, int>) {
   let mut value = 0;
   loop {
          value = channel.recv();
          if(value == -1) { break; }
          value += 1;
          channel.send(value);
   }
}

fn main() {
let(from, to) = DuplexStream();

   do spawn {
      do_task(&to);
   }

    do spawn {
        for num in range(0, 5) {
            from.send(num);
            println(from.recv().to_str());
        }
       from.send(-1);
    }
    println("Tasks spawned!");
}

Practical

  • Easy interface to C code
  • Static, native compliation using LLVM
  • Ability to break the rules

Easy interface to C code

use std::libc::{c_char, c_int, c_void, c_uint, c_ushort};


pub type PRBool = c_int;
pub type PRStatus = c_int;

pub static PRTrue: PRBool = 1;
pub static PRFalse: PRBool = 0;

pub static PRSuccess: PRStatus = 0;
pub static PRFailure: PRStatus = -1;

pub static PR_AF_INET: c_ushort = 2;

pub struct PRNetAddr {
     family: c_ushort,
     port: c_ushort,
     ip: c_uint,
     pad: [c_char, ..8],

}

#[link_args = "-lnspr4"]
extern "C" {  
pub fn PR_OpenTCPSocket(af: c_ushort) -> *c_void;
pub fn PR_Connect(fd: *c_void, addr: *PRNetAddr, timout: c_uint) -> PRStatus;
pub fn PR_Close(fd: *c_void) -> PRStatus;
pub fn PR_StringToNetAddr(string: *c_char, addr: *c_void) -> PRStatus;
pub fn PR_GetError() -> c_int;
pub fn PR_ErrorToName(error: c_int) -> *c_char;
pub fn PR_htons(conversion: c_ushort) -> c_ushort;
pub fn PR_htonl(conversion: c_uint) -> c_uint;
pub fn PR_Write(fd: *c_void, buf: *c_void, amount: c_int) -> c_int;
pub fn PR_Read(fd: *c_void, buf: *c_void, amount: c_int) -> c_int;
}

Static, native complication using LLVM

Means it's fast!

Ability to break the rules

pub fn get_nss_error() -> ~str {
    unsafe { 
        let err = PR_GetError();
        let name = PR_ErrorToName(err);
        if(name != ptr::null()) {
        std::str::raw::from_c_str(name)
        } else {
            ~"Unknown Error"
        }
    }
}

Would you like to know more?

Of course you would!

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

http://twitter.com/rustlang

irc://irc.mozilla.org/#rustlang

http://reddit.com/r/rust