Duda sobre el uso de macros en Rust

Publicado por Brisa
hace 2 meses

Hola a todos,

Estoy trabajando en un proyecto en Rust y necesito utilizar macros para generar código repetitivo de manera automática. Sin embargo, estoy teniendo problemas con la expansión de la macro. No puedo entender por qué no está generando el código esperado.

Aquí está el código de la macro:

macro_rules! generate_code {
    ($x:expr) => {
        fn generate_code() {
            // generando código...
            println!("Generando código para {}", $x);
        }
    };
}

Y aquí está el código donde intento utilizar la macro:

generate_code!("foo");

Cuando compilo el código, obtengo el siguiente error:

error: expected expression, found `generate_code`
 --> src/main.rs:10:1
  |
10 | generate_code!("foo");
  | ^^^^^^^^^^^^^^^^^^ unexpected macro invocation

No entiendo por qué la macro no está funcionando correctamente. ¿Alguien puede ayudarme a identificar el problema y encontrar una solución?

Gracias de antemano.

macros expansión código
Respuesta de Gordon Shumway
hace 2 meses

¡Hola Brisa!

El problema que estás enfrentando es debido a que la macro no se está utilizando de la manera correcta para generar una función. Además, el identificador de la función está codificado de manera literal dentro de la macro como generate_code, lo que no permitirá la creación de más de una función con ese nombre. En lugar de eso, probablemente quieras que el identificador de la función sea definido dinámicamente. Aquí te dejo una versión modificada de tu macro:

macro_rules! generate_code {
    ($func_name:ident, $x:expr) => {
        fn $func_name() {
            // generando código...
            println!("Generando código para {}", $x);
        }
    };
}

Y la usas así:

generate_code!(my_generated_function, "foo");

fn main() {
    my_generated_function();
}

He añadido un nuevo identificador a la macro $func_name:ident, el cual te permitirá definir el nombre de la función generada al momento de invocar la macro. De esta manera, cada vez que uses la macro podrás generar una nueva función con un nombre único y el argumento que quieras imprimir.

Recuerda que las macros en Rust realizan una expansión simple de código y no evalúan las expresiones que les pasas. Esto significa que necesitas proveer los nombres de las cosas (como los identificadores de funciones) de manera directa cuando usas macros.

Espero que esto solucione tu problema. ¡Suerte con tu proyecto!