0Pricing
Learn Rust Coding · Aula

Macros Procedurais: Derive e Função

Aprofunde-se nas macros procedurais, incluindo macros `#[derive]` personalizadas e macros semelhantes a funções, para gerar código mais complexo.

Macros Procedurais: Derive e Função é uma aula grátis de Learn Rust Coding no CoddyKit. Esta é a aula 2 de 3. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Learn Rust Coding, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Learn Rust Coding inclui 3 aulas no total.

Introdução às macros procedurais

Bem-vindo ao mundo das macros procedurais! Diferentemente das macros declarativas (macro_rules!), as macros procedurais são semelhantes a funções que operam diretamente sobre o código Rust.

Elas recebem um TokenStream como entrada, processam-no e retornam outro TokenStream. Isso permite uma geração de código muito mais complexa.

Tipos de macros procedurais

O Rust oferece três tipos principais de macros procedurais:

  • Macros semelhantes a funções: têm a aparência e o comportamento de chamadas de função comuns, por exemplo, my_macro!(...).
  • Macros derive: permitem implementar características automaticamente para estruturas e enumerações usando #[derive(MyTrait)].
  • Macros de atributo: permitem definir atributos personalizados que podem ser aplicados a itens, por exemplo, #[route("/path")].

A crate `proc-macro`

As macros procedurais devem ficar em seu próprio tipo especial de crate. No seu Cargo.toml, declare-a assim:

Isso informa ao Cargo que a crate contém macros que transformam código em tempo de compilação.

[package]
name = "my_macros"
version = "0.1.0"
edition = "2021"

[lib]
proc-macro = true

Macros semelhantes a funções explicadas

Macros semelhantes a funções são definidas com o atributo #[proc_macro] em uma função que recebe um proc_macro::TokenStream e retorna um.

Elas são úteis para DSLs personalizadas (linguagens específicas de domínio) ou para repetições complexas de código que macro_rules! não consegue tratar.

use proc_macro::TokenStream;

#[proc_macro]
pub fn my_function_macro(input: TokenStream) -> TokenStream {
    // Logic to transform input TokenStream
    // ...
    input // For example, return the input unchanged
}

Exemplo de macro semelhante a uma função

Aqui está um exemplo conceitual. Uma macro `greet_name!` que gera uma instrução de exibição. A implementação real analisaria a entrada TokenStream para extrair o nome.

Embora a definição da macro seja complexa, seu uso é simples e poderoso:

/* In 'my_macros/src/lib.rs' */
use proc_macro::TokenStream;

#[proc_macro]
pub fn greet_name(input: TokenStream) -> TokenStream {
    // Imagine parsing 'input' to get a name like 'World'
    // and generating: println!("Hello, World!");
    "println!(\"Hello, {}!\", \"CoddyKit\");".parse().unwrap()
}

/* In 'my_app/src/main.rs' */
use my_macros::greet_name;

fn main() {
    greet_name!("CoddyKit");
}

Entendendo macros `#[derive]`

Macros derive são o tipo mais comum. Elas permitem implementar automaticamente uma característica para uma estrutura ou enumeração.

Quando você escreve #[derive(Debug)], uma macro é executada em tempo de compilação para gerar o código necessário para que seu tipo implemente a característica Debug.

Implementando um `#[derive]` (conceito)

As macros personalizadas de derivação normalmente são construídas usando bibliotecas como syn (para analisar código Rust em uma AST) e quote (para gerar código Rust a partir de uma AST).

Você definiria uma função anotada com #[proc_macro_derive(MyTrait)] que recebe um TokenStream representando a estrutura ou enumeração e retorna a implementação gerada do traço.

/* In 'my_macros/src/lib.rs' */
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
use quote::quote;

#[proc_macro_derive(MyDebug)] // MyDebug is the trait name
pub fn my_debug_derive(input: TokenStream) -> TokenStream {
    let ast = parse_macro_input!(input as DeriveInput);
    let name = &ast.ident;

    let expanded = quote! {
        impl std::fmt::Debug for #name {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                f.debug_struct(stringify!(#name)).finish()
            }
        }
    };
    expanded.into()
}

Exemplo usando `#[derive(Debug)]`

Vamos ver um exemplo prático de uma macro de derivação que você provavelmente já usou: Debug. Ao adicionar #[derive(Debug)] à nossa estrutura Point, o Rust implementa automaticamente o traço Debug, permitindo imprimir seu conteúdo de forma organizada.

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p = Point { x: 10, y: 20 };
    println!("My point is: {:?}", p);
}

Macros de atributos: `#[my_attribute]`

Macros de atributos são semelhantes às macros de derivação, mas podem ser aplicadas a qualquer item (funções, estruturas, módulos etc.). Elas recebem como entrada o item ao qual estão associadas, além de quaisquer argumentos entre parênteses.

Usos comuns incluem roteamento de estruturas web (por exemplo, #[get("/users")]) ou configuração de testes (por exemplo, #[test]).

/* In 'my_macros/src/lib.rs' */
use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn log_calls(attr: TokenStream, item: TokenStream) -> TokenStream {
    // Imagine adding println! statements to 'item'
    item
}

/* In 'my_app/src/main.rs' */
use my_macros::log_calls;

#[log_calls("entry_point")]
fn my_function() {
    println!("Inside my_function");
}

fn main() {
    my_function();
}

Quando usar cada macro

  • Macros semelhantes a funções: para minilinguagens personalizadas ou transformações complexas de blocos de código arbitrários.
  • Macros de derivação: para implementar automaticamente traços em estruturas e enumerações.
  • Macros de atributos: para modificar ou gerar código ao redor de itens específicos (funções, estruturas) com base em atributos personalizados.

Cada tipo tem uma finalidade própria na extensão da sintaxe e dos recursos do Rust.

Verificação rápida: tipos de macros

Quais das afirmações a seguir sobre macros procedurais são TRUE?

Recapitulação: o poder da geração de código

Você explorou o mundo avançado das macros procedurais!

  • Aprendemos sobre macros semelhantes a funções para criar sintaxe personalizada.
  • Entendemos como as macros #[derive] automatizam implementações de traços.
  • Vimos brevemente as macros de atributos para geração de código no nível dos itens.

As macros procedurais são uma ferramenta poderosa para reduzir código repetitivo e ampliar os recursos do Rust, permitindo escrever código que escreve código!

Perguntas Frequentes

A aula “Macros Procedurais: Derive e Função” é grátis?

Sim — o texto completo de “Macros Procedurais: Derive e Função” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Learn Rust Coding, atualize para CoddyKit PRO. O curso de Learn Rust Coding inclui 3 aulas no total.

O que vou aprender em “Macros Procedurais: Derive e Função”?

Aprofunde-se nas macros procedurais, incluindo macros `#[derive]` personalizadas e macros semelhantes a funções, para gerar código mais complexo. Você pratica Learn Rust Coding com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Learn Rust Coding?

Nenhuma experiência prévia é necessária. Learn Rust Coding no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 3.

Quanto tempo leva a aula “Macros Procedurais: Derive e Função”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Learn Rust Coding?

Sim. Cada aula de Learn Rust Coding inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Macros Declarativas (`macro_rules!`)
  2. Macros Procedurais: Derive e Função
  3. Interação com Rust Não Seguro
← Voltar para Learn Rust Coding