Porque Você Deveria Aprender Rust

Porque Você DEVE Aprender Rust

Me

História

  • Criada em 2006 por Graydon Hoare.
  • Patrocinada pela Mozilla em 2009.
  • Versão 1.0 em 2015.
  • Versão atual: 1.38

História

Basic (com números e estruturado), dBase III Plus, Clipper, Pascal, Cobol, Delphi (ObjectPascal), C, C++, ActionScript (Flash), PHP, JavaScript, Python, Objective-C, Clojure, Java, Scala , Rust.

A language that doesn't affect the way you think about programming, is not worth knowing.
-- Alan Perlis, "ALGOL"

1. A Linguagem Mais Amada

A linguagem mais amada segundo o StackOverflow Survey 2019

... pelo 4⁰ ano seguido.

2. "Low Level Language with High Level Abstractions"

Resultado final com performance semelhante ao C...

... mas com abstrações em algo nível

  • Strings sem tamanho fixo
  • Listas
  • Mapas

3. Compilador Chato mas Amigável


fn main() -> u8 {
    let a = 2;
    a = 3;
    println!("{}", a);
    a
}
                        

3 |     let a = 2;
  |         -
  |         |
  |         first assignment to `a`
  |         help: make this binding mutable: `mut a`
4 |     a = 3;
  |     ^^^^^ cannot assign twice to immutable variable
                        

3 |     let a = 2;
  |         -
  |         |
  |         first assignment to `a`
  |         help: make this binding mutable: `mut a`
4 |     a = 3;
  |     ^^^^^ cannot assign twice to immutable variable
                        

3 |     let a = 2;
  |         -
  |         |
  |         first assignment to `a`
  |         help: make this binding mutable: `mut a`
4 |     a = 3;
  |     ^^^^^ cannot assign twice to immutable variable
                        

4. Borrow Checker


let a = String::from("hello");
                        
"Variável a tem o valor "hello""
"Posição de memória apontada por a tem o valor "hello""

0x3f5cbf89 = "hello"
                            

fn main() {
    let a = String::from("hello");
    let _b = a;
    println!("{}", a)
}
                        

error[E0382]: borrow of moved value: `a`
 --> src/main.rs:5:20
  |
4 |     let _b = a;
  |              - value moved here
5 |     println!("{}", a)
  |                    ^ value borrowed here after move
  |
  = note: move occurs because `a` has type 
    `std::string::String`, which does not 
    implement the `Copy` trait
                        

E se eu precisar acessar a variável em mais de um lugar?

References


fn main() {
    let a = String::from("hello");
    let _b = &a;
    println!("{}", a)
}
                        

Regras do Borrow Checker

Uma região de memória tem apenas um dono.

Passar um valor (região de memória) de uma variável para outra, troca o dono.

A região é desalocada quando o dono sair de escopo.

Drop


pub fn drop<T>(_x: T) { }
                        

Regras do Borrow Checker

Uma região de memória pode ter infinitas referências.

... desde que elas não durem mais do que o dono.

Regras do Borrow Checker

É possível ter uma referência mutável de uma região de memória.

... mas para haver uma referência mutável ela deve ser a única referência.

Microsoft: 70 percent of all security bugs are memory safety issues
Swift 5 Exclusivity Enforcement

Hora da anedota!

localtime

SimpleDateFormatter

Rust resolveria isso?

SIM

... porque nem ia compilar.

5. Tipos Algébricos

enum


enum IpAddr {
   V4,
   V6
}
                        

enum IpAddr {
    V4(String),
    V6(String),
}
                        

let home = IpAddr::V4(String::from("127.0.0.1"));

match home {
    V4(address) => println!("IPv4 addr: {}", address),
    V6(address) => println!("Ipv6 addr: {}", address),
}
                        

6. Error Control


try:
    something()
except Exception:
    pass
                        

try {
   something();
} catch (Exception ex) {
   System.out.println(ex);
}
                        

FILE* f = fopen("someting.txt", "wb");
fprintf(f, "Done!");
fclose(f);
                        
Onde o erro foi tratado nisso?

enum Result<T, E> {
    Ok(T),
    Err(E),
}
                        

match File::create("something.txt") {
    Ok(fp) => fp.write_all(b"Hello world"),
    Err(err) => println!("Failure! {}", err),
}
                        

match File::create("something.txt") {
    Ok(fp) => match fp.write_all(b"Hello world") {
        Ok(_) => (),
        Err(err) => println!("Can't write! {}", err),
    }
    Err(err) => println!("Failure! {}", err),
}
                        

let mut file = File::create("something.txt").unwrap();
file.write(b"Hello world").unwrap();
                        

let mut file = File::create("something.txt")?;
file.write(b"Hello world")?;
OK(())
                        

7. Generics/Traits

Structs


struct Gift {
    package_color: String,
    content: String
}
                        

Structs


let presente = Gift { package_color: "red", content: "A GIFT!" };
                        

Structs Genéricas


struct Point<T> {
    x: T,
    y: T
}
                        

Structs Genéricas


let my_point = Point<f32>(x: 1.0, y: 2.0);
                        

Enums Generics


enum Result<T, E> {
    Ok(T),
    Err(E),
}
                        

Traits


trait Summary {
    fn summarize(&self) -> String;
}
                        

struct Phrase {
    phrase: String
}

impl Summary for Phrase {
    fn summarize(&self) -> String {
        self.phrase
            .split_whitespace()
            .map(|word| word.chars().nth(0).unwrap())
            .collect()
    }
}
                        

fn get_summary<T>(summarizable: T) -> String
    where T: Summary
{
    ...
}
                        

8. Cargo

"Cargo is the Rust package manager"

"Cargo downloads your Rust package’s dependencies, compiles your packages, makes distributable packages, and uploads them to crates.io, the Rust community’s package registry."

9. Tests


#[cfg(test)]
mod tests {
    #[test]
    fn testing() {
    }
}
                        

$ cargo test
   Compiling adder v0.1.0 (file:///projects/adder)
    Finished dev [unoptimized + debuginfo] target(s) in 0.22 secs
     Running target/debug/deps/adder-ce99bcc2479f4607

running 1 test
test tests::testing ... ok
                        

10. Macros

?

Log-Derive


#[logfn(ok = "TRACE", err = "ERROR")]
fn call_isan(num: &str) -> Result<Success, Error> {
    if num.len() >= 10 && num.len() <= 15 {
        Ok(Success)
    } else {
        Err(Error)
    }
}
                        

11. Crazy stuff

4.5k issues no Github
rustup
armv7-unknown-linux-gnueabihf
wasm32-unknown-unknown (WebAssembly)

E agora?