XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Это список всех указателей:
• block
• expr используют для обозначения выражений
• ident используют для обозначения имени переменной/функции
• item
• literal используется для литеральных констант
• pat (образец)
• path
• stmt (единственный оператор)
• tt (единственное дерево лексем)
• ty (тип)
• vis (спецификатор видимости)
Полный список указателей, вы можете увидеть в Rust Reference.
Макросы могут быть перегружены, принимая различные комбинации аргументов. В этом плане, macro_rules! может работать аналогично блоку сопоставления (match):
// `test!` будет сравнивать `$left` и `$right`
// по разному, в зависимости от того, как вы объявите их:
macro_rules! test {
// Не нужно разделять аргументы запятой.
// Можно использовать любой шаблон!
($left:expr; and $right:expr) => (
println!("{:?} и {:?} это {:?}",
stringify!($left),
stringify!($right),
$left && $right)
);
// ^ каждый блок должен заканчиваться точкой с запятой.
($left:expr; or $right:expr) => (
println!("{:?} или {:?} это {:?}",
stringify!($left),
stringify!($right),
$left || $right)
);
}
fn main() {
test!(1i32 + 1 == 2i32; and 2i32 * 2 == 4i32);
test!(true; or false);
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Макросы могут использовать знак + в списке аргументов, чтобы указать, какие аргументы могут повторяться хоть один раз, или знак *, чтобы указать, какие аргументы могут повторяться ноль или несколько раз.
В следующем примере, шаблон, окружённый $(...),+ будет сопоставлять одно или несколько выражений, разделённых запятыми. Также обратите внимание, что точка с запятой является необязательной в последнем случае.
// `min!` посчитает минимальное число аргументов.
macro_rules! find_min {
// Простой вариант:
($x:expr) => ($x);
// `$x` следует хотя бы одному `$y,`
($x:expr, $($y:expr),+) => (
// Вызовем `find_min!` на конце `$y`
std::cmp::min($x, find_min!($($y),+))
)
}
fn main() {
println!("{}", find_min!(1u32));
println!("{}", find_min!(1u32 + 2 , 2u32));
println!("{}", find_min!(5u32, 2u32 * 3, 4u32));
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Макросы позволяют писать DRY код, путём разделения общих частей функций и/или набор тестов. Вот пример, который реализует и тестирует операторы +=, *= и -= на Vec<T>:
use std::ops::{Add, Mul, Sub};
macro_rules! assert_equal_len {
// Указатель `tt` (единственное дерево лексем) используют для
// операторов и лексем.
($a:expr, $b:expr, $func:ident, $op:tt) => (
assert!($a.len() == $b.len(),
"{:?}: несоответствие размеров: {:?} {:?} {:?}",
stringify!($func),
($a.len(),),
stringify!($op),
($b.len(),));
)
}
macro_rules! op {
($func:ident, $bound:ident, $op:tt, $method:ident) => (
fn $func<T: $bound<T, Output=T> + Copy>(xs: &mut Vec<T>, ys: &Vec<T>) {