Как написать макрос, который отображает номер файла, строки и переменное количество аргументов?
Я нашел в Rust несколько полезных макросов, а именно:
file!(), line!(), stringify!()
Я также обнаружил, что Rust допускает макросы с переменными аргументами, как указано здесь:
macro_rules! print_all {
($($args:expr),*) => {{
$(
println!("{}", $args);
)*
}}
}
Моя цель - каким-то образом объединить все эти макросы внутри одного, который я буду использовать во время устранения неполадок / отладки. Так зову
trace!
макрос на следующем примере:
let a: i32 = 1;
let b: i32 = 2;
trace!(a,b)
должен расшириться примерно до этого:
println!("TRACE: file: {}, line: {}, a: {}, b: {}", file!(), line!(), a, b);
Является ли это возможным? Если да, то как будет работать такой макрос?
1 ответ
Вы можете сделать что-то вроде этого:
macro_rules! trace {
($($args: expr),*) => {
print!("TRACE: file: {}, line: {}", file!(), line!());
$(
print!(", {}: {}", stringify!($args), $args);
)*
println!(""); // to get a new line at the end
}
}
Скорее всего, вызовы связаны с небольшими накладными расходами
print!
несколько раз, поскольку каждый вызов приводит к системному вызову, а также проверяет наличие ошибок ввода-вывода. Однако для создания единой строки форматирования для произвольных аргументов потребуется процедурный макрос, что, как мне кажется, выходит за рамки вопроса.
Вы также можете использовать
BufWriter
ограничить его одним системным вызовом, но это может не стоить усилий.