Skip to content

Instantly share code, notes, and snippets.

@lauromoura
Last active July 9, 2019 03:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lauromoura/cd68850f489018efb77e8219ccf6cae4 to your computer and use it in GitHub Desktop.
Save lauromoura/cd68850f489018efb77e8219ccf6cae4 to your computer and use it in GitHub Desktop.
Notes from the Rust Book

Notes from Rust Book

Building blocks

Variables and constants

let some_immutable_var = 42; // i32 typing inferred
// Would crash: some_immutable_var += 3;
let mut mutable_var = 3.14;
mutable_var += 1.78;

const SOME_CONST = 1984; // Must be a compile-time expression

Complex types

  • Tuples

    • May group different types

    • Fixed length

    • Acesso tup.0 (tup.IDX)

let tup : (i32, f64, u8) = (500, 6.4, 1);
let a = tup.0; // a = 500;
let (x, y, z) = tup; // Destructuring
  • Array

    • Fixed size

    • Panics when trying to access out of bounds

let myarr : [i32, 5] = [5, 4, 3, 2, 1];
let x = myarr[2];
let y = myarr[5]; // PANIC!!!

Expressions

  • Last expression in a block is the return value from the block if ; is absent

  • if can be used in place of a ternary operator

    • let number = if condition { something } else { another_thing };

Looping

  • loop makes an infinite loop

    • Exits with break

    • The expression after break is the return value.

let mut i = 0;
let result = loop {
    i += 1;
    if i == 5 {
        break i * 3;
    }
};
  • while is like loop, but with a checking condition

    • But does not return a value

  • for goes over elements in an iterator

let col = [1, 2, 3, 5, 8, 13, 21];
for element in col.iter() {
    println!("Element is {}", element);
}

Ownership

  • Stack vs heap

  • Rules

    • Each value has a variable that is its //Owner//

    • There can be a single owner at a time

    • The the owner goes out of scope, the value is destroyed

  • Stack stored types are just copied around

  • String as an example of heap stored value

  • Moving

    • Assignment moves data from an owner to a new one

  • Copy trait

    • The Copy trait allows owners to be copied instead of moved

    • Can’t be mixed with the Drop trait

    • Simple scalar values

    • Tuples of all fields implementing the Copy trait

  • Passing arguments to a function

    • Same semantics as assignment

    • Parameters are either moved or copied

  • Returning values from functions

Borrowing

  • Immutable references

    • There can be multiple immutable refs

    • NOP when go out of scope

  • Single mutable reference at a give scope

    • Also no immutable references while there is one mutable around

Slices

  • "Views" into the string

    • Byte addressed

    • Means an immutable borrow into the string

  • Syntax for creating: &s[start..end]

    • Indexes similar to python

    • Indexes optionals

    • Indexes must be in the boundaries of UTF8 chars

  • Syntax for returning: &str

  • String literals are also slices

    • Meaning they are immutable borrows

  • String slices can be used as parameter type for greater flexibility than regular parameters

  • Slices can be used for other collections too, like &[i32] for arrays of i32

Structs

Example of struct
struct Vector {
    x: f64,
    y: f64,
    z: f64,
}
Tuple structs
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

let c = Color(0, 0, 0);
let p = Point(0, 0, 0);
  • Despite having the same "value", c and p have different types.

  • Can be deconstructed like regular tuples

  • Struct ownership of references owned by someone else requires lifetime tags.

  • Unit-like structs have no fields

    • Useful for trait tags

  • Struct ownership of references owned by someone else requires lifetime tags.

  • Use the #[derive(Debug)] macro in the struct declaration to allow printing it.

Struct methods

  • Methods go inside an impl NAME block

  • With self first parameter, with the type of the Struct

    • But the same modifiers of mutable, borrow applies here

  • Associated methods

    • Like "static" methods. Plain functions namespaced in the class.

    • Accessed with :: separator instead of just .

  • Can have multiple impl blocks

Enums

Enum example
enum IpAddrKind {
        V4,
        V6,
}
//...
let x = IpAddrKind::V4;
Enums with values
enum IpAddr {
        V4(u8, u8, u8, u8),
        V6(String),
}
//...
let x = IpAddr::V4(127, 0, 0, 1);
More enums with values
struct Ipv4Addr{
//
}
struct Ipv6ADdr{
//
}
enum IpAddr {
        V4(Ipv4Addr),
        V6(Ipv6Addr),
}
...
let x = IpAddr::V4(127, 0, 0, 1);
  • Enums can also have impl blocks to implement Methods

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

let someNumber = Some(5);
let absentNumber : Option<i32> = None;
  • Need to handle all enum values in order to extract info from it.

Match Operator
enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: &Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}
Match on Option<T>
match opt {
        None -> None,
        Some(i) -> Some(i+1),
}
  • _ used as a placeholder for remaining values in the match

Single expression matches (if let)
if let Some(3) = some_expression {
// do something
}

Module system

  • Packages: A cargo feature that lets you build, test and share crates

  • Crates: A tree of modules that produce a library or executable

  • Modules and use: Control the organization, scope and privacy of paths

  • Paths: A way to name an item (the item’s full qualified name?)

Packages and crates

  • Crate is a binary or library

  • Crate root is the file the compiler starts from

  • A package is formed by one or more crates

    • The package contains a Cargo.toml file describing how to build these crates

    • Must contain at least one crate (either binary or library)

      • At most one library crate

      • Any number of binary crates

  • Convention of src/main.rs as the crate root of a binary crate with the same name

  • Likewise, src/lib.rs is the convention for a library crate with the same name

  • Each file in src/bin.rs means a new separate binary crate

  • Crates expose functionality through a scope with the crate name

Modules to control scope

  • Modules control visibility of stuff

  • Parent/child/sibling naming for their relationship

  • Modules can be accessed by absolute path by using the root crate:

    • crate::front_of_house::add_to_waitlist();

  • Also by relative path by using self, super or a local identifier to the current module.

    • mod_in_current_namespace::func();

    • super refers to the parent module

Privacy of stutff

  • Private by default

  • Child modules can use private stuff from parent modules

  • Parent modules can’t use private stuff from child modules

  • Think of child modules as implementation details

  • Use pub to make stuff visible

    • Needs to be applied to both the module and the members you want to expose.

  • Struct fields are also private by default

    • You can make fields public on a case by case basis

  • Enum fields are all public if the enum is public

    • Makes sense, as you may need to match all enum values

Use keyword

  • use works like Python’s from parent import module, in the sense of making module available in the current scope by its name

    • Also has the option to use as to replace the name

    • Also have the option to import everything with the * name

      • use std::collections::*;

  • Idiomatic ways of using use:

    • Functions are imported keeping their declaring module as a name qualifier

    • Structs and Enums are imported directly

  • Using pub use to re-export a name to whoever imports us

  • Multiple uses with the same prefix can be grouped together

    • use std::io::{self, Write};

Modules as files

  • Use use module_name; to load the module from module_name.rs

    • The file contents will be the module content

Common Collections

  • Vector

    • Variable number of items contiguously

  • String

    • Collection of characters

  • HashMap

    • Associate a value to a particular Key

    • Particular implementation of map

Vectors

Operations on vectors
let v1 : Vec<i32> = Vec::new();
{
        let v = vec![1, 2, 3];

        v1.push(1);
        v1.push(2);
        v1.push(3);
} // v is freed here
Reading from vector
let v1 = vec![2,4,6,8];

let third = &v1[2]; // May panic if out of bounds
match v1.get(2) {
        Some(third) => ...,
        None => ...,
}
  • Holding a reference from a Vector item works like holding a reference to a vector.

Iterating a vector
let v = vec![1,2,3];
for i in &v {
        println!("{}", i);
}

for i in &mut v {
        *i += 50;
}
Using an enum as Variant in a vector
enum Cell {
    Int(i32),
    Float(f64),
    Text(String),
}
let row = vec![
    Cell::Int(3),
    Cell::Float(3.14),
    Cell::Text(String::from("duh")),
];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment