flakolefluk.dev

Aprendiendo Rust en público - El macro println!

Haré una pausa en los ejercicios para entender mejor el macro println! ya que lo hemos estado usando en los ejercicios, pero sin comprender mucho de él.

Dejo en claro que no pretendo adentrarme en los macros o como construirlos, si no, en el funcionamiento de println! en particular.

Para intentar descifrarlo un poco más, buscaré en la documentación de rust.

Imprime a la salida estándar, con una nueva línea

Además nos da un par de ejemplos.

println!(); // imprime una nueva línea
println!("hello there!");
println!("format {} arguments", "some");

De aquí sacamos un par de cosas. El macro puede o no tener parámetros. Puede tener un sólo parametro o más.

La documentación nos sugiere entonces ir a otra sección (std:fmt) para más detalles de la sintaxis.

!!!!!!!
Al revisar la documentación, vemos que podemos hacer muchísimas cosas. Algunas me parecen que no las usaremos mucho así que me enfocaré en solo las principales (a mi gusto).

La primera regla importante es que el primer argumento (si es que lo hay) debe ser un string literal, es decir, no puede ser una variable.
Este string también nos permitirá interpolar y dar formato al resto de argumentos.

println!("un string literal");
// Imprimirá el literal tal cual, no hay niguna variable involucrada.
// output: un string literal

Parámetros #

Si añadimos más parametros estos serán interpolados/formateados segun indique el primer parámetro.

let myVariable = "variable";
println!("un string literal con una {}", myVariable);
// reemplazará {} por el segundo parámetro.
// output: un string literal con una variable

Podemos agregar tantos {}, como queramos y los valores a interpolar serán tomados de la lista de parámetros (a partir del segundo parámetro, porque el primero es el string que da formato)

let a = "tengo";
let b = "muchas";
let c = "variables";
println!("ahora {} {} {}", a, b, c);
// output: ahora tengo muchas variables

Orden de parámetros #

Los parametros reemplazados usarán el orden en que se declaran en el macro. Sin embargo haciendo uso de nuestro string literal podemos alterar el orden.
El ejemplo anterior quedaría así, usando posiciones de los parametros.:

let a = "tengo";
let b = "muchas";
let c = "variables";
println!("ahora {0} {1} {2}", a, b, c); // 0 sería el primer parametro DESPUES del string, y sigue en orden ascendente
// output: ahora tengo muchas variables

Luego si quisieramos cambiar el orden quedaría algo así:

let a = "tengo";
let b = "muchas";
let c = "variables";
println!("ahora {2} {0} {1}", a, b, c);
// output: ahora variables tengo muchas

Parámetros con nombre #

A veces confiar en el orden de los parametros puede ser algo confuso. Agregar un {} extra podría hacer que todo quedara fuera de lugar.
Tenemos otra opción para interpolar los parámetros: parámetros con nombre.
En este caso no reemplazaremos los braces {} según su orden, si no que usando un nombre asignado. Lo cual hace más sencillo insertarlo en cualquier lugar, incluso repetir los parámetros, teniendo mayor libertad (a mi gusto).

println!("{verbo} o {negacion} {verbo}", verbo="ser", negacion="no"); 
// output: ser o no ser

Existen muchísimas (muuuuchas) más posibilidades de formateo en std:fmt además de otros macros en la familia, pero por ahora nos quedamos con estas más comunes.

Queda pendiente formatear usando {:?}. Lo dejaremos para después, por que creo que nos adelantaríamos a hablar de otro tema: Traits.
Hasta ahora en los ejemplos hemos formateado usando el trait Display y {:?} usa el trait Debug. Si desean profundizar, curiosear o adelantarse hay un capítulo al respecto en el libro de Rust.

En el próximo post comenzaremos con funciones en Rust.

Para seguir esta serie, puedes buscar por el tag #aprendiendo_rust