Porque Você Deveria Aprender Rust

Porque Você DEVE Aprender Rust

Me
  • Coordenador do meetup Rust in POA
  • Co-coordenador do meetup PyTche
  • Co-coordenador do meetup Design de Código
  • Palestrante do Tchelinux

JulioBiason.me

História

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

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

Verona: Research programming language for concurrent ownership

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
					

var obj = null;
try {
   obj = get_object();
} catch (Exception ex) {
   System.out.println(ex);
}
obj.do_something();
					

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")
    .expect("ERROR OPENING");
file.write(b"Hello world")
    .expect("ERROR WRITING");
					

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);
					

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

Enums Generics


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

Traits


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

Traits


struct Phrase {
    phrase: String
}

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

Traits


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() {
    }
}
					

Tests


$ 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

?

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)

Complicações de Rust:

  • Borrow checker
  • Sem OO
  • Tempo de compilação

E agora?