Выбрать главу

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>) {