Macros - Tylung/rust-apuntes GitHub Wiki

Que es una macro?

Las macros no son más que funciones que definen como se generará un código, todas las macros se ejecutarán en la primera fase de la compilación.

Las macros funcionan bajo un concepto llamado metaprogramación

Que es la metaprogramación?

La metaprogramación es una técnica de programación en la que los programas informáticos tienen la capacidad de tratar otros programas como sus datos. Esto significa que un programa puede ser diseñado para leer, generar, analizar o transformar otros programas, e incluso modificarse a sí mismo mientras se ejecuta.

En pocas palabras, la metaprogramación implica escribir un código que puede

  • Generar el código
  • Manipular las construcciones del lenguaje en el tiempo de ejecución. Este fenómeno se conoce como Metaprogramación Reflexiva o Reflexión.

Como se usan las macros?

Rust proporciona un potente sistema de macros que permite la metaprogramación. Como has visto en capítulos anteriores, los macros parecen funciones, excepto que su nombre termina con un signo de exclamación !, pero en lugar de generar una llamada de función, los macros se expanden en el código fuente que se compila con el resto del programa. Sin embargo, a diferencia de las macros en C y otros lenguajes, los macros de Rust se expanden en árboles de sintaxis abstractos, en lugar de preprocesamiento de cadenas, por lo que no obtienes errores de precedencia inesperados.

Los macros se crean usando el macro macro_rules!.

macro_rules! di_hola {
    // `()` indica que el macro no acepta argumentos.
    () => {
        // El macro se expandirá al contenido de este bloque.
        println!("¡Hola!");
    };
}

fn main() {
    // Esta llamada se expandirá a `println!("¡Hola!");`
    di_hola!()
}

Entonces, ¿por qué son útiles los macros?

  1. No te repitas. Hay muchos casos en los que es posible que necesites una funcionalidad similar en varios lugares pero con diferentes tipos. A menudo, escribir un macro es una forma útil de evitar la repetición de código. (Más sobre esto más adelante)

  2. Lenguajes específicos de dominio. Los macros te permiten definir una sintaxis especial para un propósito específico. (Más sobre esto más adelante)

  3. Interfaces variadicas. A veces, deseas definir una interfaz que tenga un número variable de argumentos. Un ejemplo es println! que puede tomar cualquier número de argumentos, dependiendo de la cadena de formato!. (Más sobre esto más adelante)