XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Глава "The Rust Programming Language" о полном имени методов (Fully Qualified syntax)
Rust предоставляет мощную систему макросов, которая позволяет использовать метапрограммирование. Как вы могли видеть в предыдущих главах, макросы выглядят как функции, но их имя заканчивается восклицательным знаком (!). Вместо вызова функции, макросы расширяются в исходный код, который впоследствии компилируется с остальной частью программы. Однако, в отличие от макросов на C и других языках, макросы Rust расширяются в абстрактные синтаксические деревья, а не в подстановку строк, поэтому Вы не получаете неожиданных ошибок приоритета операций.
Макросы создаются с помощью макроса macro_rules!
// Этот простой макрос называется `say_hello`.
macro_rules! say_hello {
// `()` указывает, что макрос не принимает аргументов.
() => (
// Макрос будет раскрываться с содержимым этого блока.
println!("Hello!");
)
}
fn main() {
// Этот вызов будет раскрыт в код `println!("Hello");`
say_hello!()
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Так почему же макросы полезны?
1. Не повторяйтесь. Есть много случаев, когда вам может понадобиться подобная функциональность в нескольких местах, но с различными типами. Чаще всего написание макроса - это полезный способ избежать повторения кода. (Подробнее об этом позже)
2. Предметно-ориентированные языки. Макросы позволяют определить специальный синтаксис для конкретной цели. (Подробнее об этом позже)
3. Вариативные интерфейсы. Иногда вы хотите объявить интерфейс, принимающий переменное число аргументов. Например, println!, принимающий такое же число аргументов, сколько объявлено в строке с форматом. (Подробнее об этом позже)
В следующем подразделе мы посмотрим как в Rust объявить макрос. Есть три основные идеи:
• Шаблоны и указатели
• Перегрузка
• Повторение
Аргументы макроса имеют префикс знака доллара $ и тип аннотируется с помощью указателей фрагмента:
macro_rules! create_function {
// Этот макрос принимает аргумент идентификатора `ident` и
// создаёт функцию с именем `$func_name`.
// Идентификатор `ident` используют для обозначения имени переменной/функции.
($func_name:ident) => (
fn $func_name() {
// Макрос `stringify!` преобразует `ident` в строку.
println!("Вызвана функция {:?}()",
stringify!($func_name))
}
)
}
// Создадим функции с именами `foo` и `bar` используя макрос, указанный выше.
create_function!(foo);
create_function!(bar);
macro_rules! print_result {
// Этот макрос принимает выражение типа `expr` и напечатает
// его как строку вместе с результатом.
// Указатель `expr` используют для обозначения выражений.
($expression:expr) => (
// `stringify!` преобразует выражение в строку *без изменений*.
println!("{:?} = {:?}",
stringify!($expression),
$expression);
)
}
fn main() {
foo();
bar();
print_result!(1u32 + 1);
// Напомним, что блоки тоже являются выражениями!
print_result!({
let x = 1u32;
x * x + 2 * x - 1
});
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה