Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rust for Serious Developers

Rust for Serious Developers

An introduction for what Rust is, what makes it special and why it's not just a toy language but solving some real problems and will become an important tool of every technology stack.

Armin Ronacher

March 01, 2017
Tweet

More Decks by Armin Ronacher

Other Decks in Programming

Transcript

  1. Rust For Serious Developers
    Armin @mitsuhiko Ronacher

    View Slide

  2. )J *N"SNJO
    BOE*EP0QFO4PVSDF
    'MBTL
    +JOKB
    4FOUSZ
    j

    View Slide

  3. View Slide

  4. View Slide

  5. Sentry Loves Rust

    View Slide

  6. Symbolication

    View Slide

  7. View Slide

  8. Source Map Expansion

    View Slide

  9. View Slide

  10. Command Line Tool

    View Slide

  11. View Slide

  12. Hello Rust

    View Slide

  13. Ocaml
    C++
    Haskell
    Erlang
    Scheme
    C#
    ADT, Pattern Matching
    RAII, Smart Pointers
    Typeclasses
    Message Passing, Failures
    Hygienic Macros
    Attributes

    View Slide

  14. fn main() {
    println!("Hello, World!");
    }

    View Slide

  15. The Toolchain

    View Slide

  16. is so good

    View Slide

  17. curl https://sh.rustup.rs -sSf | sh
    https://win.rustup.rs
    or on windows

    View Slide

  18. rustup
    the rust toolchain manager

    View Slide

  19. rustc
    the rust compiler

    View Slide

  20. cargo
    the rust package manager

    View Slide

  21. rustdoc
    the rust documentation builder

    View Slide

  22. Quickstart

    View Slide

  23. $ cargo new --bin hello-rust
    Created binary (application) `hello-rust` project
    $ cd hello-rust
    $ cargo run
    Compiling hello-rust v0.1.0 (file:///private/tmp/hello-rust)
    Finished debug [unoptimized + debuginfo] target(s)
    Running `target/debug/hello-rust`
    Hello, world!

    View Slide

  24. Release Channels

    View Slide

  25. stable
    new release every 6 weeks

    View Slide

  26. beta
    upcoming stable release

    View Slide

  27. nightly
    includes unstable features

    View Slide

  28. $ rustup override set nightly
    info: using existing install for 'nightly-x86_64-apple-darwin'
    info: override toolchain for '/private/tmp/hello-rust' set to
    'nightly-x86_64-apple-darwin'
    nightly-x86_64-apple-darwin unchanged - rustc 1.17.0-nightly
    (0648517fa 2017-02-27)

    View Slide

  29. The Ecosystem

    View Slide

  30. crates.io
    repository of reusable rust crates

    View Slide

  31. docs.rs
    documentation for all crates

    View Slide

  32. The Features

    View Slide

  33. ADTs

    View Slide

  34. enum JsonValue {
    Null,
    Bool(bool),
    Number(f64),
    Str(String),
    List(Box>),
    Object(Box>),
    }

    View Slide

  35. fn main() {
    let value = JsonValue::Str("Hello World!".to_string());
    match value {
    JsonValue::Str(ref string) => {
    println!("JSON value as a string: {}", string);
    },
    _ => {
    println!("JSON value was something else");
    }
    }
    }

    View Slide

  36. explicit error propagation

    View Slide

  37. use std::{fs, env, io};
    fn list_current_dir() -> Result<(), io::Error> {
    let here = env::current_dir()?;
    for dent_rv in fs::read_dir(here)? {
    let dent = dent_rv?;
    let md = dent.metadata()?;
    println!("{: <60}{: <12}{}",
    dent.path().display(),
    md.len(),
    if md.is_file() { "file" } else { "dir" });
    }
    Ok(())
    }
    fn main() {
    list_current_dir().unwrap();
    }

    View Slide

  38. strong types and inference

    View Slide

  39. use std::{fs, env, io};
    use std::collections::HashMap;
    fn count_extensions() -> Result<(), io::Error> {
    let mut counts = HashMap::new();
    for dent_rv in fs::read_dir(env::current_dir()?)? {
    if let Some(ext) = dent_rv?.path().extension() {
    *counts.entry(ext.to_string_lossy().into_owned()).or_insert(0) += 1;
    }
    }
    let mut items = counts.into_iter().collect::>();
    items.sort_by_key(|&(_, value)| -value);
    for (ext, count) in items {
    println!("{: >5} {}", count, ext);
    }
    Ok(())
    }
    Result Type
    OS Str -> String
    Hash Table Entry
    Vector of Tuples

    View Slide

  40. data vs behavior

    View Slide

  41. struct User {
    id: u64,
    username: String,
    }
    impl User {
    fn new(id: u64, username: &str) -> User {
    User {
    id: id,
    username: username.to_string(),
    }
    }
    fn username(&self) -> &str {
    &self.username
    }
    }

    View Slide

  42. it's all about traits

    View Slide

  43. use std::fmt;
    impl fmt::Debug for User {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "", &self.username, self.id)
    }
    }

    View Slide

  44. compiler plugins

    View Slide

  45. #[derive(Debug, Clone, Serialize, Deserialize)]
    struct User {
    id: u64,
    username: String,
    }

    View Slide

  46. memory safety

    View Slide

  47. View Slide

  48. View Slide

  49. View Slide

  50. so how does rust do it?

    View Slide

  51. lifetimes
    move semantics
    ADTs
    smart pointers
    bounds checking
    explicit unsafe
    Reason about Memory
    Track where stuff goes
    No Null-Pointers
    Runtime Lifetimes
    Panic on OOB
    The Escape Hatch

    View Slide

  52. struct SdkInfo {
    name: String,
    version: String,
    }
    struct SdkInfo<'a> {
    name: &'a str,
    version: &'a str,
    }
    struct SdkInfo<'a> {
    name: Cow<'a, str>,
    version: Cow<'a, str>,
    }

    View Slide

  53. fn main() {
    let items = vec![1, 2, 3];
    let sitems = items.into_iter().map(|x| x.to_string()).collect::>();
    println!("Converted {} items to strings", items.len());
    }
    error[E0382]: use of moved value: `items`
    --> fail.rs:4:46
    |
    3 | let sitems = items.into_iter().map(|x| x.to_string()).collect::>();
    | ----- value moved here
    4 | println!("Converted {} items to strings", items.len());
    | ^^^^^ value used here after move
    |
    = note: move occurs because `items` has type `std::vec::Vec`,
    which does not implement the `Copy` trait
    error: aborting due to previous error

    View Slide

  54. free parallelism

    View Slide

  55. extern crate rayon;
    fn quick_sort(v: &mut [T]) {
    if v.len() > 1 {
    let mid = partition(v);
    let (low, high) = v.split_at_mut(mid);
    rayon::join(|| quick_sort(low), || quick_sort(high));
    }
    }
    fn partition(xs: &mut [T]) -> usize {
    let pivot = xs.len() - 1;
    let mut i = 0;
    for j in 0..pivot {
    if xs[j] <= xs[pivot] { xs.swap(i, j); i += 1; }
    }
    xs.swap(i, pivot);
    i
    }
    Values that order & can be sent to threads
    Spawn two threads and join
    split mutable slice into two

    View Slide

  56. struct Server {
    ctx: Arc,
    }
    impl Server {
    pub fn run(&self) -> Result<()> {
    let ctx = self.ctx.clone();
    Server::http("127.0.0.1:3000")?
    .handle(move |req: Request, resp: Response|
    {
    let local_ctx = ctx.clone();
    ...
    }
    }
    }
    increments refcount and returns new Arc

    View Slide

  57. Should you use it?

    View Slide

  58. maybe!

    View Slide

  59. Python Modules

    View Slide

  60. Redis/Nginx Modules

    View Slide

  61. Command Line Tools

    View Slide

  62. Native Libraries

    View Slide

  63. One-Trick-Pony API Servers

    View Slide

  64. Our Experience

    View Slide

  65. code is very readable

    View Slide

  66. compile times suck

    View Slide

  67. crate ecosystem is great

    View Slide

  68. highly maintainable

    View Slide

  69. QA
    &

    View Slide