Exemplo do Rust previne apenas com o compilador Vamos ver um pouco de Rust

Playground fn main () { let data = vec! () ; println! ( "Data" , data ) ; }

error: argument never used --> src/main.rs:3:22 | 3 | println!("Data", data); | ^^^^ error: aborting due to previous error

Playground fn main () { let data = vec! () ; println! ( "Data {} " , data ) ; }

error[E0277]: the trait bound `std::vec::Vec<_>: std::fmt::Display` is not satisfied --> src/main.rs:3:25 | |println!("Data {}", data); | ^^^^ `std::vec::Vec<_>` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string | = help: the trait `std::fmt::Display` is not implemented for `std::vec::Vec<_>` = note: required by `std::fmt::Display::fmt` error: aborting due to previous error

^^^^ `std::vec::Vec<_>` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string

Playground fn main () { let data = vec! () ; println! ( "Data {:?} " , data ) ; }

error[E0282]: type annotations needed --> src/main.rs:2:16 | 2 | let data = vec!(); | ---- ^^^^^^ cannot infer type for `T` | | | consider giving `data` a type | error: aborting due to previous error

error[E0282]: type annotations needed

$ rustc --explain E0282

Playground fn main () { let data : Vec < char > = vec! () ; println! ( "Data {:?} " , data ) ; }

Data []

Imagine uma base de código bem complexa Código com threads

Processamento de imagens em paralelo

Coordenar muito acesso de I/O

Em resumo, imagine quão complexo um navegador é por trás dos panos?

Existe algum problema neste código? Playground use std ::thread; use std :: time :: Duration ; fn main () { let data = vec! () ; thread ::spawn ( || { data.push ( 'a' ) ; } ) ; thread ::spawn ( || { data.push ( 'b' ) ; } ) ; thread ::sleep ( Duration ::from_millis ( 50 ) ) ; println! ( "Data {:?} " , data ) ; }

Depois de vários ciclos de feedback na compilação: Não teremos acesso a memória já liberada

Teremos adicionado uma forma forma de evitar race conditions Nosso binário não terá esses problemas!

Playground use std ::thread; use std :: sync :: { Arc , Mutex } ; use std :: time :: Duration ; fn main () { let data = Arc ::new ( Mutex ::new ( vec! () ) ) ; let writer = data.clone () ; thread ::spawn ( move || { let lock_result = writer.lock () ; match lock_result { Ok ( mut locked_writer ) => locked_writer.push ( 'a' ) , Err ( _ ) => panic! ( "Could not acquire lock a" ) , } } ) ; let writer = data.clone () ; thread ::spawn ( move || { let mut locked_writer = writer.lock () .expect ( "Could not acquire lock b" ) ; locked_writer.push ( 'b' ) ; } ) ; thread ::sleep ( Duration ::from_millis ( 50 ) ) ; println! ( "Data {:?} " , data ) ; }

Esse sistema de tipo traz novas maneiras de expressar seu domínio

Que não conseguimos fazer em outras linguagens mais conhecidas

Playground # [ derive ( Debug ) ] struct Pedido { id : i32 } fn novo_pedido () -> Pedido { Pedido { id : 1 } } fn enviar_pedido ( pedido : Pedido ) { // Código que envia o pedido } fn main () { let pedido = novo_pedido () ; enviar_pedido ( pedido ) ; println! ( "Dados do pedido: {:?} " , pedido ) ; }

error[E0382]: use of moved value: `pedido` --> src/main.rs:18:39 | 16 | enviar_pedido(pedido); | ------ value moved here 17 | 18 | println!("Dados do pedido: {:?}", pedido); | ^^^^^^ value used here after move

Só podemos acessar o pedido antes de enviarmos as informações nesse cenário

E isso é reforçado pelo compilador

Playground # [ derive ( Debug ) ] struct Pedido { id : i32 } fn novo_pedido () -> Pedido { Pedido { id : 1 } } fn enviar_pedido ( pedido : Pedido ) { // Código que envia o pedido } fn main () { let pedido = novo_pedido () ; println! ( "Dados do pedido: {:?} " , pedido ) ; enviar_pedido ( pedido ) ; }

Dados do pedido: Pedido { id: 1 }

Rust incentiva testes desde o inicio do projeto Tipos não conseguem verificar toda a lógica

pub fn super_calculo ( x : i32 , y : i32 ) -> i32 { x + y } # [ test ] fn test_super_calculo () { assert_eq! ( 3 , super_calculo ( 1 , 2 ) ) ; }

$ cargo test running 1 test test test_super_calculo ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Documentação é vista como parte importante do seu projeto

Tentando evitar que exemplos fiquem desatualizados

/// Realiza um grande cálculo que te deixará surpreso /// # Examples /// /// ``` /// use minha_lib::*; /// /// assert_eq!(5, calculo_surpresa(1, 2)); /// ``` pub fn calculo_surpresa ( x : i32 , y : i32 , z : i32 ) -> i32 { x + y + z }

Exemplos que aparecem na documentação são executados durante os testes $ cargo test [...] running 1 test test src/lib.rs - calculo_surpresa (line 4) ... FAILED failures: ---- src/lib.rs - calculo_surpresa (line 4) stdout ---- error[E0061]: this function takes 3 parameters but 2 parameters were supplied --> src/lib.rs:5:32 | 5 | assert_eq!(5, calculo_surpresa(1, 2)); | ^^^^ expected 3 parameters

Gerar a documentação do projeto é simples $ cargo doc --open

Uma linguagem de sistemas: Tem mensagens de erros claras

Que se preocupa com documentação e testes

E traz todas essas aprendizagens de outras linguagens É uma ótima evolução para todo o ecossistema de baixo nível

E uma ótima opção para construir plataformas de alto nível

Mas você não precisa se preocupar com tudo isso agora

Essas foram exemplos de possibilidades e potencial da linguagem

Você pode aprender aos poucos, na sua velocidade