stringify! în Rust

Transformă codul primit în text, fără să-l execute. Folosit în macro-uri pentru mesaje care arată expresia exactă.

Sintaxă
stringify!(orice cod)     // -> "orice cod" (&'static str), codul NU este executat

Ce face stringify!

stringify!(a + b * 2) nu calculează nimic: dă textul "a + b * 2". Codul primit nu trebuie nici măcar să fie valid ca expresie, doar să fie format din tokeni Rust. Textul rezultat păstrează în mare scrierea ta (spațiile multiple dintre tokeni devin unul singur), dar forma exactă nu este garantată.

Este folosit mai ales în macro-uri, ca să afișeze codul cu care au fost apelate. Așa funcționează mesajele lui assert! (assertion failed: x > 0) și dbg! ([main.rs:3:5] a * 2 = 10).

Rezultatul este un literal de text (&'static str), deci poate fi combinat cu concat!.

Exemple

Exemplul 1: Codul devine text

Nicio expresie nu este evaluată: nici funcția inexistentă, nici împărțirea la zero. Pe al treilea rând se vede că spațiile multiple au devenit unul singur, iar restul scrierii a rămas cum era.

fn main() {
    println!("{}", stringify!(pret * cantitate + transport));
    println!("{}", stringify!(functie_inexistenta(1/0)));
    println!("{}", stringify!(a+b   *2));
    println!("{}", stringify!(Vec<String>));
}

Rezultat

pret * cantitate + transport
functie_inexistenta(1/0)
a+b *2
Vec<String>

Exemplul 2: Un macro de verificare care arată expresia

verifica! afișează textul condiției și rezultatul ei, ca un assert! care nu oprește programul.

macro_rules! verifica {
    ($conditie:expr) => {
        println!("{:<30} {}", stringify!($conditie), if $conditie { "DA" } else { "NU" })
    };
}

fn main() {
    let varsta = 17;
    let oras = "Iași";
    verifica!(varsta >= 18);
    verifica!(oras.starts_with("I"));
    verifica!(oras.chars().count() == 4);
}

Rezultat

varsta >= 18                   NU
oras.starts_with("I")          DA
oras.chars().count() == 4      DA

Greșeli frecvente

  • Te aștepți ca stringify!(x) să dea valoarea lui x. Dă textul "x"; pentru valoare folosește format!("{x}").
  • Te bazezi pe spațierea exactă a rezultatului (de exemplu în teste). Formatarea textului produs nu este garantată între versiunile de Rust.

Comenzi înrudite

  • concat!: Lipește literali (texte, numere, bool, char) într-un singur &’static str, la compilare, fără niciun cost la rulare.
  • macro_rules!: Definește un macro propriu: cod care scrie cod la compilare, după tipare. Așa sunt construite println!, vec! sau assert_eq!.
  • assert! și debug_assert!: Verifică o condiție la rulare și dă panică dacă este falsă. debug_assert! face verificarea doar în modul debug, nu și în release.
  • dbg!: Afișează rapid, pentru depanare, fișierul, linia, expresia și valoarea ei (în format Debug) pe stderr, apoi returnează valoarea.