Ce face format_args!
format_args! este temelia tuturor macro-urilor de formatare: println!, format! și write! îl apelează intern. El verifică șablonul la compilare și produce o valoare std::fmt::Arguments, care ține șablonul și referințe la argumente. Textul propriu-zis nu este construit și nu se alocă memorie până când cineva nu scrie valoarea undeva.
Îl folosești când scrii propriile funcții de jurnalizare sau afișare: funcția primește fmt::Arguments, iar apelantul îi dă format_args!(...). Valoarea Arguments implementează Display, deci poate fi afișată cu {} sau scrisă cu write_fmt.
Rezultatul lui format_args! împrumută argumentele, deci de obicei se folosește imediat, în aceeași expresie (de exemplu ca argument de funcție), nu se păstrează într-o variabilă pentru mai târziu. Dacă șablonul nu are argumente, as_str() returnează textul ca &'static str; altfel returnează None.
Exemple
Exemplul 1: O funcție de jurnal care primește fmt::Arguments
jurnal adaugă nivelul în față. Macro-ul info! transmite șablonul și argumentele mai departe prin format_args!, deci se scrie la fel de comod ca println!.
use std::fmt;
fn jurnal(nivel: &str, mesaj: fmt::Arguments) {
println!("[{nivel:<5}] {mesaj}");
}
macro_rules! info {
($($arg:tt)*) => { jurnal("INFO", format_args!($($arg)*)) };
}
fn main() {
let utilizator = "ana";
info!("{utilizator} s-a autentificat");
info!("comanda {} are {} produse", 1042, 3);
jurnal("EROARE", format_args!("plata pentru comanda {} a eșuat", 1043));
}
Rezultat
[INFO ] ana s-a autentificat
[INFO ] comanda 1042 are 3 produse
[EROARE] plata pentru comanda 1043 a eșuat
Exemplul 2: Scriere fără String intermediar și as_str
write_fmt scrie direct valoarea Arguments în destinație. as_str() dă textul când șablonul nu are argumente de formatat și None când are.
use std::io::{self, Write};
fn main() -> io::Result<()> {
let mut iesire = io::stdout().lock();
let pret = 49.9;
iesire.write_fmt(format_args!("Preț: {pret:.2} lei\n"))?;
let n = 5;
println!("{:?}", format_args!("text fix").as_str());
println!("{:?}", format_args!("cu argument {}", n).as_str());
Ok(())
}
Rezultat
Preț: 49.90 lei
Some("text fix")
None
Greșeli frecvente
- Salvezi rezultatul într-o variabilă cu argumente temporare (
let a = format_args!("{}", x + 1);) și îl folosești mai târziu: eroaretemporary value dropped while borrowed. Folosește-l direct, ca argument. - Folosești
format!în funcțiile de jurnal care, de cele mai multe ori, nu afișează nimic (de exemplu mesaje de depanare dezactivate). Cufmt::Argumentstextul se construiește doar dacă este chiar scris.
Comenzi înrudite
format! (și sintaxa de formatare): Construiește un String nou din șablon și valori, cu aceeași sintaxă ca println!, dar fără să afișeze nimic.write! și writeln!: Scriu text formatat într-o destinație aleasă: un String, un fișier, stdout sau Formatter-ul din Display. Returnează un Result.println! și print!: Afișează text pe ieșirea standard: println! adaugă la final un rând nou, print! nu. Acoladele {} sunt înlocuite cu valori.macro_rules!: Definește un macro propriu: cod care scrie cod la compilare, după tipare. Așa sunt construite println!, vec! sau assert_eq!.