The concept of macro macros is found in many languages.
In general, the mechanism of a macro is to replace or expanded a macro that has already been defined at the pre-compilation stage, that is, to replace the macro by its name with the contents of the macro.
The macros in Rust are different!
The macros in rust are also processed during the pre-compilation phase. Macros are not just replacements and unwinding, they can also receive parameters and invoke other macros like function functions.
A simple macro
The name of the macro is similar to the function name, except there is an exclamation mark after the function name!
A simple macro definition and invocation:
macro_rules! say_hello{ ()=>( println!("Hello"); ) } fn main(){ say_hello!()
Explain:
macro_rules! Declare a macro, Say_hello is the name of the macro, Say_hello is followed by a pair of curly braces, which is the content body of the macro.
The "=" in front of the curly braces indicates that the macro has no input parameters.
Inside this macro, another macro is called println!
The macro is called in the main () function function. Because this macro and the calling function function in a file, there is no need for additional export and introduction of macro declarations.
Of course, the contents of the macro can be used () in addition to the {} curly braces; and [];
macro_rules! say_hello ( ()=>( println!("Hello"); ) );
macro_rules! say_hello [ ()=>( println!("Hello"); ) ];
? Attention:
- When using curly braces, there is no semicolon behind the curly braces;
- When using () and [], there is a semicolon behind it.
If curly braces {} have semicolons, or () and [] no semicolons compile errors.
? Attention:
Another important note is that the macro input parameters are included in the macro content body!!!
Second, the macro with parameters
The following defines a macro with parameters Print_hello
macro_rules! print_hello{ ($msg:expr) =>( println!("hello{}", $msg); )}fn main(){ print_hello!(",world!");}
The above defines a Print_hello macro that breaks down the above code into 4 parts:
First section: Macro declaration
- macro_rules! is a macro definition keyword, note the following! Exclamation mark
- followed by the name of the macro this is the name that defines the macro
Part Two: The content boundary of the macro {pair of curly braces}
macro_rules! print_hello {}
Part III: Contents of a macro-content in curly braces
The contents of the curly braces are called macro rule macros. A macro can contain any (0-n) multiple macro rule macros.
($msg:expr) =>( println!("hello{}", $msg) );($msg:expr) =>{ println!("hello{}", $msg) };($msg:expr) =>[ println!("hello{}", $msg) ];($msg:expr) => ( println!("hello{}", $msg); );($msg:expr) => { println!("hello{}", $msg); };($msg:expr) => [ println!("hello{}", $msg); ];
The above 6 sentences function exactly the same!
The format of the macro rule should be this:
( ) => { };( ) => [ ];( ) => ( );
- Each macro rule has a = =;
- The parentheses to the left are the input parameters of the rule, the form of which is called a Matcher match;
- In the parentheses to the right is the content of the macro, which needs to be executed or replaced, called the Transcriber Converter, which can be a statement, an expression, and so on.
The above three lines of code are equivalent.
Matcher and Transcriber will be described in detail later in the article.
As I said earlier, the macro parameters are contained within the macro content body!
Compare the declaration format of the function function:
fn fn_name(x:i32,y:u32){ }
The input parameters of the function function are passed in through the parentheses following the Fn_name, and the parameters may be 0 or more, but all parameters must be declared in this parenthesis.
Take a look at this code:
macro_rules! foo { $e:expr) => (println!("mode X: {}"$e)); $e:expr) => (println!("mode Y: {}"$e));}fn main() { 7); 3);}
The input to the macro is not passed through the parameter list! instead, they are searched or matched by match.
When matching to x = 7, perform mode X:7
When matching to Y = 3, perform mode Y:3
Part IV: Macro invocation
print_hello!(",world!");
Call the method, use the macro name after add! An exclamation mark, followed by an exclamation mark, indicates an input parameter.
The macro macro-syntax analysis and use examples of Rust 1.7.0