Introduction to The Rust
Programming Language
http://www.rust-lang.org
Nikolay Denev <nikolay.denev@williamhill.com>
History and Origins
• Started as a personal project by Graydon Hoare from Mozilla some
time around 2008
• Officially recognized as Mozilla sponsored project from 2009 and first
announced in 2010
• First Pre-Alpha release in January 2012
• First Stable release 1.0 in May 2015
• Currently at 1.12.1 (stable)
• Follows 6 week release cycle with Stable, Beta and Nightly branches.
• Mozilla’s experimental browser engine Servo is being written in Rust.
Goals and Features
• Designed as a systems programming language focusing on:
• Safety – Statically typed with extensive compile time validations.
• Speed – Compiled, allows low level access similar to C/C++.
• Concurrency – Built in support for threads, channels.
• Major features:
• Zero-cost abstractions (you pay only for what you use), Trait based generics
• Algebraic data types (enum), pattern matching.
• Move semantics / Borrow checks at compile time.
• Guaranteed memory safety and threading without data races.
• Type inference, Minimal Runtime (no garbage collector).
• Immutable bindings by default.
Generics, Zero cost abstractions
Pay only for what you use
• Trait based generics are monomorphised by default (static dispatch),
• Dynamic (vtable) dispatch possible using Trait objects.
struct Foo{ foo: String };
struct Bar{ bar: String };
trait FooBar {
fn fubar(&self) -> String;
}
impl FooBar for Foo {
fn fubar(&self) -> String {
self.foo.clone()
}
}
impl FooBar for Bar {
fn fubar(&self) -> String {
self.bar.clone()
}
}
Generics, Zero cost abstractions
Pay only for what you use
• Trait based generics are monomorphised by default (static dispatch),
• Dynamic (vtable) dispatch possible using Trait objects.
let foo = Foo { foo: “foo”.to_string() };
let bar = Bar { bar: “bar”.to_string() };
fn statically_dispatched_generic_function<T>(o: &T) -> String where T: FooBar {
o.foobar()
}
fn dynamically_dispatched_generic_function(o: &GetSome) -> String {
o.foobar()
}
assert_eq!(statically_dispatched_generic_function(foo, “foo”.to_string());
assert_eq!(statically_dispatched_generic_function(bar, “bar”.to_string());
assert_eq!(dynamically_dispatched_generic_function(foo, “foo”.to_string());
assert_eq!(dynamically_dispatched_generic_function(bar, “bar”.to_string());
Algebraic data types (enums)
Pattern matching and destructuring.
Enums in Rust represent a type with one of several possible variants,
with each variant optionally having associated data with it.
enum Fubar {
Foo(String),
Bar(String),
Fubar,
FooBar { id: String, count: u64 },
}
let x = Fubar::Foo(“foo”); // or let x = Fubar::Bar(“bar”); or …
match x {
Foo(s) => println!(“{}”, s), // or: Foo(s) | Bar(s), 1 … 3, Foo(_)
Bar(s) => println!(“{}”, s),
Fubar => println!(“FOOBAR!”),
FooBar(i, c) => println!(“Id: {}, count: {}”, i, c), // or: FooBar(i, c) if c > 5 => …
// _ => panic(“default”);
}
Move semantics a.k.a. the concept of ownership.
The Borrow Checker.
• Type and ownership/borrow checking at compile time ensures:
• Using a value typically means transfer of ownership.
• Only one mutable reference can exist.
• Or multiple immutable references can exist.
fn print(s: String) { println!(“{}”, s); }
let x = “something”.to_string();
print(x);
print(x);
error[E0382]: use of moved value: `x`
--> src/main.rs:4:7
3 | print(x);
| - value moved here
4 | print(x);
| ^ value used here after move
= note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy`
trait
Move semantics a.k.a. the concept of ownership.
The Borrow Checker.
• Type and ownership/borrow checking at compile time ensures:
• Using a value typically means transfer of ownership.
• Only one mutable reference can exist.
• Or multiple immutable references can exist.
or
fn print(s: &String) { println!(“{}”, s); }
let x = “something”.to_string();
print(&x);
print(&x);
fn print(s: String) { println!(“{}”, s); }
let x = “something”.to_string();
print(x.clone());
print(x.clone());
Move semantics a.k.a. the concept of ownership.
The Borrow Checker.
• Type and ownership/borrow checking at compile time ensures:
• Using a value typically means transfer of ownership.
• Only one mutable reference can exist.
• Or multiple immutable references can exist.
let x = String::from(“some”);
x.push_str(“thing”);
error: cannot borrow immutable local variable `x` as mutable
--> src/main.rs:1:1
|
1 | let x = String::from("some");
| - use `mut x` here to make mutable
2 | x.push_str("thing");
| ^ cannot borrow mutably
Move semantics a.k.a. the concept of ownership.
The Borrow Checker.
• Type and ownership/borrow checking at compile time ensures:
• Using a value typically means transfer of ownership.
• Only one mutable reference can exist.
• Or multiple immutable references.
let mut x = String::from(“some”);
x.push_str(“thing”);
assert_eq!(x, “something”.to_string());
Move semantics a.k.a. the concept of ownership.
The Borrow Checker and Lifetimes.
• Most of the time you don’t need to explicitly specify lifetimes,
however in some cases it is necessary:
struct Something<'a> {
id: &'a str,
}
impl<'a> Something<'a> {
fn id_ref(&'a self) -> &'a str {
self.id
}
}
fn main() {
// let s: &’static str = “static string”;
let s = Something { id: &String::from("something") };
assert_eq!("something", s.id_ref());
}
And much more
• String types (owned, vs slice).
• Stack allocation by default, or Box<>-ed for Heap allocation.
• Closures
• Cargo package manager, dependency and build tool
• Unsafe{}
• Concurrency: Send and Sync traits. Smart pointers like Arc<>,
Mutex<>, RwLock<>
• Async IO : mio, Futures
Additional resources
• https://www.rust-lang.org
• https://crates.io
• https://doc.rust-lang.org/stable/book
^^^ (previously known as Rust for Rubyists  )
• https://this-week-in-rust.org
• https://github.com/kud1ing/awesome-rust
• …. much more …
Questions?

Introduction to the rust programming language

  • 1.
    Introduction to TheRust Programming Language http://www.rust-lang.org Nikolay Denev <nikolay.denev@williamhill.com>
  • 2.
    History and Origins •Started as a personal project by Graydon Hoare from Mozilla some time around 2008 • Officially recognized as Mozilla sponsored project from 2009 and first announced in 2010 • First Pre-Alpha release in January 2012 • First Stable release 1.0 in May 2015 • Currently at 1.12.1 (stable) • Follows 6 week release cycle with Stable, Beta and Nightly branches. • Mozilla’s experimental browser engine Servo is being written in Rust.
  • 3.
    Goals and Features •Designed as a systems programming language focusing on: • Safety – Statically typed with extensive compile time validations. • Speed – Compiled, allows low level access similar to C/C++. • Concurrency – Built in support for threads, channels. • Major features: • Zero-cost abstractions (you pay only for what you use), Trait based generics • Algebraic data types (enum), pattern matching. • Move semantics / Borrow checks at compile time. • Guaranteed memory safety and threading without data races. • Type inference, Minimal Runtime (no garbage collector). • Immutable bindings by default.
  • 4.
    Generics, Zero costabstractions Pay only for what you use • Trait based generics are monomorphised by default (static dispatch), • Dynamic (vtable) dispatch possible using Trait objects. struct Foo{ foo: String }; struct Bar{ bar: String }; trait FooBar { fn fubar(&self) -> String; } impl FooBar for Foo { fn fubar(&self) -> String { self.foo.clone() } } impl FooBar for Bar { fn fubar(&self) -> String { self.bar.clone() } }
  • 5.
    Generics, Zero costabstractions Pay only for what you use • Trait based generics are monomorphised by default (static dispatch), • Dynamic (vtable) dispatch possible using Trait objects. let foo = Foo { foo: “foo”.to_string() }; let bar = Bar { bar: “bar”.to_string() }; fn statically_dispatched_generic_function<T>(o: &T) -> String where T: FooBar { o.foobar() } fn dynamically_dispatched_generic_function(o: &GetSome) -> String { o.foobar() } assert_eq!(statically_dispatched_generic_function(foo, “foo”.to_string()); assert_eq!(statically_dispatched_generic_function(bar, “bar”.to_string()); assert_eq!(dynamically_dispatched_generic_function(foo, “foo”.to_string()); assert_eq!(dynamically_dispatched_generic_function(bar, “bar”.to_string());
  • 6.
    Algebraic data types(enums) Pattern matching and destructuring. Enums in Rust represent a type with one of several possible variants, with each variant optionally having associated data with it. enum Fubar { Foo(String), Bar(String), Fubar, FooBar { id: String, count: u64 }, } let x = Fubar::Foo(“foo”); // or let x = Fubar::Bar(“bar”); or … match x { Foo(s) => println!(“{}”, s), // or: Foo(s) | Bar(s), 1 … 3, Foo(_) Bar(s) => println!(“{}”, s), Fubar => println!(“FOOBAR!”), FooBar(i, c) => println!(“Id: {}, count: {}”, i, c), // or: FooBar(i, c) if c > 5 => … // _ => panic(“default”); }
  • 7.
    Move semantics a.k.a.the concept of ownership. The Borrow Checker. • Type and ownership/borrow checking at compile time ensures: • Using a value typically means transfer of ownership. • Only one mutable reference can exist. • Or multiple immutable references can exist. fn print(s: String) { println!(“{}”, s); } let x = “something”.to_string(); print(x); print(x); error[E0382]: use of moved value: `x` --> src/main.rs:4:7 3 | print(x); | - value moved here 4 | print(x); | ^ value used here after move = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
  • 8.
    Move semantics a.k.a.the concept of ownership. The Borrow Checker. • Type and ownership/borrow checking at compile time ensures: • Using a value typically means transfer of ownership. • Only one mutable reference can exist. • Or multiple immutable references can exist. or fn print(s: &String) { println!(“{}”, s); } let x = “something”.to_string(); print(&x); print(&x); fn print(s: String) { println!(“{}”, s); } let x = “something”.to_string(); print(x.clone()); print(x.clone());
  • 9.
    Move semantics a.k.a.the concept of ownership. The Borrow Checker. • Type and ownership/borrow checking at compile time ensures: • Using a value typically means transfer of ownership. • Only one mutable reference can exist. • Or multiple immutable references can exist. let x = String::from(“some”); x.push_str(“thing”); error: cannot borrow immutable local variable `x` as mutable --> src/main.rs:1:1 | 1 | let x = String::from("some"); | - use `mut x` here to make mutable 2 | x.push_str("thing"); | ^ cannot borrow mutably
  • 10.
    Move semantics a.k.a.the concept of ownership. The Borrow Checker. • Type and ownership/borrow checking at compile time ensures: • Using a value typically means transfer of ownership. • Only one mutable reference can exist. • Or multiple immutable references. let mut x = String::from(“some”); x.push_str(“thing”); assert_eq!(x, “something”.to_string());
  • 11.
    Move semantics a.k.a.the concept of ownership. The Borrow Checker and Lifetimes. • Most of the time you don’t need to explicitly specify lifetimes, however in some cases it is necessary: struct Something<'a> { id: &'a str, } impl<'a> Something<'a> { fn id_ref(&'a self) -> &'a str { self.id } } fn main() { // let s: &’static str = “static string”; let s = Something { id: &String::from("something") }; assert_eq!("something", s.id_ref()); }
  • 12.
    And much more •String types (owned, vs slice). • Stack allocation by default, or Box<>-ed for Heap allocation. • Closures • Cargo package manager, dependency and build tool • Unsafe{} • Concurrency: Send and Sync traits. Smart pointers like Arc<>, Mutex<>, RwLock<> • Async IO : mio, Futures
  • 13.
    Additional resources • https://www.rust-lang.org •https://crates.io • https://doc.rust-lang.org/stable/book ^^^ (previously known as Rust for Rubyists  ) • https://this-week-in-rust.org • https://github.com/kud1ing/awesome-rust • …. much more …
  • 14.