Hello everyone, new episode of rust series is here. Today it's going to be some introduction of Rust macros. Macros in Rust bring even more flexibility to Rust language. We already know many macros like println!, vec! and some others. When you see something ending with exclamation mark in rust you can be quite sure it's a macro. It mostly means that it has special syntax and special features which are out of scope of standard function syntax.
Macros has some advantages and some disadvantages:
- advantages: richer syntax, features
- disadvantages: harder to read, harder to write
Standard library macros
There are various macros that we are commonly using
- panic! - causes current thread to panic (panic!("unexpected state!");)
- vec! - macro for creating vectors (let v = vec![1,2,3];)
- try! - macro that takes Result<T,E> and either gives Ok value or returns error out from enclosing function
- assert! - basic assertion (assert!(result_below_ten < 10);)
- assert_eq! - basic equality assertion (assert!(result_zero_expected, 0);)
- unreachable! - macro suited for unreachable code (unreachable!();)
- unimplemented! - for code that is not yet implemented (unimplemented!());
Creating own macros
Creating macro stars with calling macro_rules! ... ehm macro :).
Simple macro
Let's write simple echo macro. You can object that for this we don't need macro at all and you're right. But it illustrates basic syntax.
macro_rules! echo {
($x:expr) => {
println!("Call:{}", $x);
println!("Echo:{}", $x);
}
}
fn main() {
echo!("Halooo Steemit!");
}
# output
Call:Halloo Seemit!
Echo:Halloo Steemit!
$x:expr here is any Rust expression, $x is meta variable. Then "=>" referes to block where meta variables can be used.
Multiple values
We can also have multiple optional parameters (which normal function cannot accept). Then we use special expression:
macro_rules! multilines {
( $( $x:expr ),* ) => {
{
$(
println!($x);
)*
}
};
}
fn main() {
multlines!("first line","second line","third line");
}
# output
first line
second line
third line
$(...),* means zero or more expressions
$(...),+ means one or more expressions
Macro matching parameters
It's also possible to construct macro that can match input parameter. Check this code
macro_rules! macro_xy {
(x => $e:expr) => (println!("x matched, value = {}", $e));
(y => $e:expr) => (println!("y matched, value = {}", $e));
}
fn main() {
macro_xy!(x => 4);
macro_xy!(y => 5);
}
# output
x matched, value = 4
y matched, value = 5
There is much more to macros but these basic should illustrate enough how they are written and should be easier to write more complex constructions.
Postfix
That's all for now, thank you for your appreciations, feel free to comment and point out possible mistakes (first 24 hours works the best but any time is fine). May Jesus bless your programming skills, use them wisely and see you next time.
Meanwhile, you can also check the official documentation to know more about writing macros