Les macros en Rust són una eina poderosa que permet als programadors escriure codi que genera codi. Això pot ser molt útil per evitar la repetició i per crear abstraccions més altes. En aquest tema, explorarem què són les macros, com es defineixen i utilitzen, i veurem alguns exemples pràctics.

Què són les Macros?

Les macros en Rust permeten definir patrons de codi que es poden expandir en codi real durant la compilació. Això és diferent de les funcions, ja que les macros operen en el codi font abans que aquest sigui compilat.

Tipus de Macros

  1. Macros per a Procediments: Són similars a les funcions, però operen en el codi font.
  2. Macros per a Derivació: S'utilitzen per implementar automàticament trets per a structs i enums.
  3. Macros Declaratives: Són les més comunes i es defineixen amb macro_rules!.

Definició de Macros Declaratives

Les macros declaratives es defineixen amb la sintaxi macro_rules!. A continuació es mostra un exemple bàsic:

macro_rules! di_hola {
    () => {
        println!("Hola, món!");
    };
}

Explicació del Codi

  • macro_rules! di_hola: Defineix una macro anomenada di_hola.
  • () => { ... }: Defineix un patró que no pren arguments i expandeix a println!("Hola, món!");.

Ús de la Macro

fn main() {
    di_hola!();
}

Quan s'executa aquest codi, la sortida serà:

Hola, món!

Macros amb Arguments

Les macros també poden acceptar arguments. Vegem un exemple:

macro_rules! suma {
    ($a:expr, $b:expr) => {
        println!("La suma de {} i {} és {}", $a, $b, $a + $b);
    };
}

Explicació del Codi

  • $a:expr, $b:expr: Defineix dos arguments que són expressions.
  • println!("La suma de {} i {} és {}", $a, $b, $a + $b);: Expandeix a una crida a println! que mostra la suma dels dos arguments.

Ús de la Macro

fn main() {
    suma!(3, 5);
}

Quan s'executa aquest codi, la sortida serà:

La suma de 3 i 5 és 8

Exemples Pràctics

Macro per a Repetició

Una macro que repeteix una acció un nombre determinat de vegades:

macro_rules! repeteix {
    ($n:expr, $e:expr) => {
        for _ in 0..$n {
            $e
        }
    };
}

Ús de la Macro

fn main() {
    repeteix!(3, println!("Això es repeteix tres vegades"));
}

Quan s'executa aquest codi, la sortida serà:

Això es repeteix tres vegades
Això es repeteix tres vegades
Això es repeteix tres vegades

Errors Comuns

  1. No tancar correctament els delimitadors: Assegura't que tots els parèntesis, claudàtors i claus estiguin correctament tancats.
  2. Confusió entre funcions i macros: Recorda que les macros s'invoquen amb ! (ex. di_hola!();).

Exercicis Pràctics

Exercici 1: Macro de Multiplicació

Defineix una macro anomenada multiplica que accepti dos arguments i imprimeixi el resultat de la seva multiplicació.

macro_rules! multiplica {
    // Defineix la macro aquí
}

fn main() {
    multiplica!(4, 5);
}

Solució

macro_rules! multiplica {
    ($a:expr, $b:expr) => {
        println!("La multiplicació de {} i {} és {}", $a, $b, $a * $b);
    };
}

fn main() {
    multiplica!(4, 5);
}

Exercici 2: Macro de Salutació Personalitzada

Defineix una macro anomenada saluda que accepti un nom com a argument i imprimeixi una salutació personalitzada.

macro_rules! saluda {
    // Defineix la macro aquí
}

fn main() {
    saluda!("Anna");
}

Solució

macro_rules! saluda {
    ($nom:expr) => {
        println!("Hola, {}!", $nom);
    };
}

fn main() {
    saluda!("Anna");
}

Conclusió

Les macros en Rust són una eina molt potent per generar codi de manera dinàmica i evitar la repetició. Hem vist com definir i utilitzar macros declaratives, així com alguns exemples pràctics. Amb la pràctica, les macros poden ajudar-te a escriure codi més eficient i mantenible.

© Copyright 2024. Tots els drets reservats