Files
rust-by-example/src/macros.rs

104 lines
2.4 KiB
Rust

// Group functionality with different types
// Define special syntac for specific purpose
// Variable number of arguments
// Different combination of arguments
macro_rules! say_hello {
() => {
println!("Hello world!");
};
}
// Types of arguments have designators:
// block
// expr is used for expressions
// ident is used for variable/function names
// item
// literal is used for literal constants
// pat (pattern)
// path
// stmt (statement)
// tt (token tree)
// ty (type)
// vis (visibility qualifier)
macro_rules! generate_function {
($func_name:ident) => {
fn $func_name() {
println!("You called {:?}()", stringify!($func_name));
}
};
}
generate_function!(foo);
macro_rules! process_expression {
($expression: expr) => {
println!("{:?} = {:?}", stringify!($expression), $expression);
};
}
// Overload
macro_rules! match_block {
($left: expr; and $right: expr) => {
println!("A: {:?} and {:?}", stringify!($left), stringify!($right))
};
($left: expr; or $right:expr) => {
println!(
"B: {:?} or {:?} is {:?}",
stringify!($left),
stringify!($right),
$left || $right
)
};
}
// Repeat: variable number of args o a type
macro_rules! find_max {
($x:expr) => ($x);
($x:expr, $($y:expr), +) => (std::cmp::max($x, find_max!($($y), +)));
}
// DSLs: Domain Specific Languages
// macro_rules allows you to create your own syntax
macro_rules! calc {
(eval $e:expr) => {
println!("{} = {}", stringify!($e), $e);
};
}
macro_rules! calculate {
(eval $e: expr) => {
{
let val: usize = $e; // Force types to be integers
println!("{} = {}", stringify!{$e}, val);
}
};
(eval $e: expr, $(eval $y: expr), +) => {{
calculate!{eval $e}
calculate!{ $(eval $y), + }
}};
}
pub fn macros_rule() {
foo();
say_hello!();
process_expression!(1 + 5 * 3);
match_block!(1i32 + 1 == 2i32; and 2i32 * 2 == 4i32); // Enters first branch
match_block!(true; or false); // Enter second branch
match_block!(true; and true); // Enters first branch
println!("Max is {}", find_max!(5, 3 * 8, 4, 9 * 5));
calc! {
eval (1 + 2) * 4
}
calculate! {
eval (1 + 2) * 4,
eval 1 + 5,
eval 7 + 4,
eval 3 + 9
}
}