Skip to main content

Introdução | Rust

  • Introdução | Rust

Padrões (defaults) no Rust

AspectoPadrão no RustComo alterarExemplo
ImutabilidadeImutável por padrãomutlet mut x = 10;
VisibilidadePrivado por padrãopub, pub(crate), pub(super)pub fn f() {}
OwnershipMove por padrãoBorrow (&, &mut) ou Clonelet b = a; (move)
BorrowingImutável por padrão&mut para mutável&x vs &mut x
NullNão existeOption<T>Some(x) / None
ErrosExplícitosResult<T, E>fn f() -> Result<T, E>
ExceçõesNão usadas por padrãopanic! (caso extremo)panic!("erro")
Coerção de tiposNão implícitaas, into(), from()x as i64
Pattern matchingExaustivo obrigatório_ ou todos os casosmatch x { ... }
ImportsExplícitosuseuse crate::mod::Item;
Traits (comportamento)Não implícitosimplimpl Trait for T {}
Concorrência seguraGarantida em compile-timeunsafe para ignorarSend, Sync
Struct fieldsPrivados por padrãopub nos campospub nome: String
EnumsFortemente tipados e exaustivos_ ou todos os variantsenum X { A, B }
Variáveis não usadasWarning por padrão_ prefixolet _x = 10;
Funções puras (sem efeito)Incentivadosem side-effects
Heap vs StackStack por padrãoBox, Rc, ArcBox::new(x)

alt text

Como instalar o Rust?


Compilation Targets

  • O objetivo principal do compiler do rust é converter código rust em código de máquina

Release Channels

  • stable
  • beta - candidato para a próxima release
  • nightly - construido na master toda noite

Sintaxe

danger

Por padrão, tudo é imutável no Rust

info

No Rust, self é uma referência ao próprio objeto ou instância de uma struct ou enum dentro de um método ou função associada. Ele é usado para acessar os membros (campos e métodos) da instância dentro de uma implementação.

    println!("{}", val);
print!("{:p}", val); // é usado para imprimir o endereço de memória de um ponteiro.


Variáveis imutáveis e mutáveis

    let message = ""; // imutável
let mut message2 = ""; //mutável

let x: i32 = 5;
let y: bool = false;
let z: &str = "teste";
let list: [u8; 3] = [1, 2, 3];

// 2^8 - 1 = 255
let small_num: u8 = 5;

//-128 to 127
let small_num: i8 = 5;

//operating system related types
let sys_num: isize = -5;
let sys_num_2: usize = 5;

let hex_num = 0xfa;
let oct_num = 0o77;
let bin_num = 0b1010;
let byte_num = b'A';
let custom_num = 98_000;
let float_num: f32 = 3.14;
let float_num_2: f32 = 2.0;

let tuple = (20,3.12,1);
print!("{}", tuple.0);
print!("{:?}", tuple);

let x = [2; 6]; // [2,2,2,2,2,2]

Funções | Rust

fn nome(variavel: &str) -> &str{
return "";
}

Acessar métodos de classes

String::from();
Classe::ChamarMetodo();

Retornar valores passado por parâmetro

fn main(){
let a = "Hello, ";
let d = extendend_message(a);
println!("{}", d);
}

fn extendend_message(mut a: &str) -> String {
a.push_str("Hello, world!");
return a;
}

Fazer referência

fn main(){
let message = String::from("Hello, ");
let message_2 = &message; // immutable reference

let mut messageMut = String::from("Hello, ");
let message_3 = &mut messageMut; //mutable reference
}

* (asterístico) | Rust

O * em Rust é o operador de desreferenciação, e seu objetivo é acessar o valor subjacente a que um ponteiro ou referência está apontando.

let x = 10;
let y = &x; // y é uma referência ao valor de x

println!("{}", *y); // Desreferencia y para acessar o valor de x (10)

Box

  let num = 32;
let num_3 = Box::new(32);
println!("num = {}", num);

Struct | Rust

  • No Rust, uma struct (abreviação de "estrutura") é uma forma de agrupar diferentes tipos de dados em um único tipo personalizado. É equivalente a "objetos" em linguagens orientadas a objetos, embora Rust não tenha o conceito de métodos diretamente acoplados aos dados (isso é feito com impl).

As structs no Rust são uma forma fundamental de organizar e encapsular dados.

// tipo 1
struct Person{
name: String,
age: u8
}

// tipo 2
struct Coordenada(f32, f32);

// tipo 3
struct SomenteUm;


fn main(){
let person = Person{name: String::from("John"), age: 25};
println!("Name: {} Age: {}", person.name, person.age);
}

Métodos | Rust

  • Para adicionar métodos estáticos ou métodos que necessita de uma referência, usa o impl
struct Person{
name: String,
age: u8
}

impl Person{
// constructor
fn new() -> Person{
Person{
name: String::from("John"),
age: 25
}
}

//método estático
fn some_function(){
println!("Some function");
}

//método de instancia
fn some_change(self){
println!("Some change");
}

// referência imutável
fn some_change2(&self){
println!("Some change");
}

// referência mutável
fn some_change3(&mut self){
println!("Some change");
}

}

fn main(){
Person::some_function();
let person = Person{name: String::from("John"), age: 25};
person.some_change();
}

#[derive(Debug)] | Rust

  • Em Rust, a anotação #[derive(Debug)] é usada para gerar automaticamente uma implementação do trait Debug para um tipo, como uma enum, struct, ou union. O trait Debug é um dos traços padrões de Rust que permite representar um valor de forma legível para depuração, ou seja, fornece uma maneira de imprimir o valor de uma variável de forma útil durante o desenvolvimento e depuração do código
#[derive(Debug)]
enum Status {
Active,
Inactive,
Pending,
}

fn main() {
let status = Status::Active;

// Usando o trait Debug para imprimir
println!("{:?}", status);
}

  • #[derive(Debug)]: Essa anotação instrui o compilador a gerar automaticamente a implementação do trait Debug para a enum Status.

  • {:?}: O {:?} é um especificador de formatação usado dentro de println! para imprimir o valor de algo que implementa o trait Debug. Quando você usa {:?}, Rust chama o método fmt::Debug na instância para gerar uma representação textual legível.

Enums | Rust

enum Cor {
Vermelho,
Verde,
Azul,
}

Aqui, Cor é um enum com três variantes: Vermelho, Verde e Azul.

Variantes com Dados

Cada variante pode armazenar dados. Isso pode ser útil para representar estados mais complexos.

enum Resultado {
Sucesso(i32),
Falha(String),
}

Neste caso, Sucesso armazena um valor inteiro, e Falha armazena uma String.

Uso de Enums | Rust

Você pode criar instâncias de enum com as variantes e acessar seus dados de forma padrão:

let cor = Cor::Vermelho;

let resultado = Resultado::Sucesso(200);

match resultado {
Resultado::Sucesso(codigo) => println!("Sucesso com código: {}", codigo),
Resultado::Falha(mensagem) => println!("Falha: {}", mensagem),
}

No exemplo acima, o match permite tratar cada variante de forma específica.

Enums e Métodos | Rust

Você pode definir métodos para os seus enums, assim como para structs:

impl Cor {
fn descricao(&self) -> &str {
match self {
Cor::Vermelho => "Vermelho",
Cor::Verde => "Verde",
Cor::Azul => "Azul",
}
}
}

If Else | Rust

if let <condicao> {

}else{

}

trait

  • Em Rust, um trait é um mecanismo que permite definir um conjunto de métodos ou comportamentos que podem ser implementados por diferentes tipos. Em outras palavras, é uma maneira de especificar funcionalidades compartilhadas entre tipos, sem precisar de herança como em outras linguagens orientadas a objetos.
// Definindo um trait
trait Saudacao {
fn cumprimentar(&self) -> String;
}

// Implementando o trait para um tipo específico
struct Pessoa {
nome: String,
}

impl Saudacao for Pessoa {
fn cumprimentar(&self) -> String {
format!("Olá, meu nome é {}", self.nome)
}
}

fn main() {
let pessoa = Pessoa {
nome: String::from("João"),
};

println!("{}", pessoa.cumprimentar()); // Saída: Olá, meu nome é João
}

Mod

info

Uma das formas caso o módulo esteja em outro arquivo é usar o use meu_modulo::saudar no começo do arquivo onde desejo importar

mod meu_modulo {
pub fn saudar() {
println!("Olá do módulo!");
}
}

fn main() {
// Para acessar itens de um módulo, você deve usar seu nome:
meu_modulo::saudar();
}

//crate::learning_rust::....
//crate points to -> src/lib.rs and src/main.rs

//super::outsider()
//super -> going outside 1 level of current module