No description
Find a file
2026-09-01 13:36:09 +02:00
.woodpecker chore: migrate CI to .woodpecker/{push,branch}.yml 2026-09-01 13:36:09 +02:00
src fix(028): pedagogical MINOR fixes 2026-09-01 13:36:09 +02:00
tests fix: content audit corrections (accuracy, coherence, concordância, tests) 2026-09-01 13:36:09 +02:00
.gitignore Initial commit 2026-09-01 11:35:50 +00:00
Cargo.lock initial content 2026-09-01 13:36:07 +02:00
Cargo.toml chore: declare MSRV 1.85 (edition 2024) 2026-09-01 13:36:09 +02:00
LICENSE chore: add AGPL-3.0 license and standard .gitignore 2026-09-01 13:36:09 +02:00
README.md fix(028): pedagogical MINOR fixes 2026-09-01 13:36:09 +02:00

Lição 28: Sistemas Universais (Generics)

1. Narrativa

O piloto do mecha Æther aprende a construir sistemas que funcionam com QUALQUER tipo de dado — componentes universais que se adaptam a qualquer carga, sensor ou módulo. Generics (<T>) permitem escrever código flexível sem duplicação, como um slot universal que aceita qualquer equipamento.

2. Conceito

Generics parametrizam tipos, permitindo código reutilizável:

  • Funções genéricas: fn trocar<T>(a: &mut T, b: &mut T) — funciona com qualquer tipo
  • Structs genéricas: struct Compartimento<T> — armazena qualquer coisa
  • Enums genéricas: enum Varredura<T> — como Option customizado
  • Múltiplos tipos: <T, U> — dois parâmetros independentes
  • Trait bounds: where T: Trait — restringir quais tipos são aceitos

3. Requisitos

  • Criar funções genéricas com <T> e <T, U>
  • Definir structs e enums genéricos
  • Implementar métodos genéricos com impl<T>
  • Usar closures como parâmetros genéricos (FnOnce(T) -> U)

4. Design de Dados

graph TD
    A["fn trocar<T>"] --> B[Troca qualquer tipo]
    C["struct Compartimento<T>"] --> D["Option<T> interno"]
    E["struct Canal<A, B>"] --> F["esquerda: A, direita: B"]
    G["enum Varredura<T>"] --> H["Detectado(T) | Vazio"]
    I["struct Pilha<T>"] --> J["Vec<T> interno"]

5. Diagrama de Fluxo

flowchart TD
    A[Início] --> B{Tipo de dado?}
    B -->|Trocar| C["trocar<T>(&mut a, &mut b)"]
    B -->|Armazenar| D["Compartimento<T>::guardar(item)"]
    B -->|Empilhar| E["Pilha<T>::empilhar(item)"]
    B -->|Varredura| F["Varredura<T>::detectado(item)"]
    C --> G[Genérico funciona com qualquer T]
    D --> G
    E --> G
    F --> G

6. Funções

Função Descrição
trocar Troca dois valores de qualquer tipo
maior_indice Retorna o maior entre dois usize
criar_par Cria tupla com tipos possivelmente diferentes
inverter_par Inverte (T, U) para (U, T)
Compartimento::novo Cria compartimento vazio
Compartimento::com_item Cria compartimento com item
Compartimento::guardar Armazena item, retorna anterior
Compartimento::retirar Remove e retorna item
Compartimento::mapear Transforma conteúdo com closure
Canal::novo Cria canal com dois lados
Canal::inverter Inverte os lados do canal
Varredura::detectado Cria varredura com item
Varredura::vazio Cria varredura vazia
Varredura::obter_deteccao Extrai referência do item
Varredura::transformar Transforma conteúdo com closure
Sinal::unidade Cria sinal unitário
Sinal::duplo Cria sinal duplo
Sinal::esta_ativo Verifica se há sinal
Pilha::nova Cria pilha vazia
Pilha::empilhar Adiciona ao topo
Pilha::desempilhar Remove do topo
Registro::novo Cria registro com tag
Registro::transformar Transforma dado mantendo tag

7. Exemplo

let mut comp: Compartimento<i32> = Compartimento::novo();
comp.guardar(42);
assert_eq!(comp.retirar(), Some(42));
let par = criar_par("sensor", 100);
let invertido = inverter_par(par);
assert_eq!(invertido, (100, "sensor"));

8. Missão

  1. Implementar funções genéricas: trocar, criar_par, inverter_par
  2. Implementar Compartimento<T>: novo, com_item, guardar, retirar, mapear
  3. Implementar Canal<A, B>: novo, inverter
  4. Implementar Varredura<T>: detectado, vazio, foi_detectado, obter_deteccao, transformar
  5. Implementar Sinal<T, U>: unidade, duplo, silencio, esta_ativo
  6. Implementar Pilha<T>: nova, empilhar, desempilhar, tamanho, esta_vazia, espiar
  7. Implementar Registro<T>: novo, transformar

9. Como Executar

cargo build
cargo test
cargo clippy -- -D warnings
cargo fmt --check

10. Dicas

  • Monomorfização: o compilador gera código específico para cada tipo usado — zero custo em runtime
  • impl<T> deve repetir o parâmetro <T> antes do bloco
  • FnOnce(T) -> U consome a closure — use Fn para chamadas múltiplas
  • Option é o enum genérico mais usado em Rust — Varredura<T> segue o mesmo padrão
  • Trocar valores: use std::mem::swap(a, b). Uma variável temporária (let temp = *a;) NÃO compila para tipos não-Copy como String (erro E0507) — moveria o valor para fora da referência
  • Avançado (Lição 33): mapear/transformar recebem closures (FnOnce) — você as estudará na Lição 33. Por ora, entenda que são funções anônimas passadas como argumento