当前位置:网站首页>[rust notes] 18 macro
[rust notes] 18 macro
2022-07-06 03:19:00 【phial03】
18 - macro
assert_eq!
macro : An error message containing the assertion file name and line number can be generated .macro : Is a way to extend the language . During compilation , Before checking the type and generating any machine code , Every macro call will be extended (expanded).
assert_eq!(gcd(6, 10), 2); // The code after the above macro expansion match (&gcd(6, 10), &2) { (left_val, right_val) => { if !(*left_val == *right_val) { panic!("assertion failed: '(left == right)', \ (left: '{:?}', rigth: '{:?}')", left_val, right_val); } } }
Rust Macros can be integrated with other components of the language , Not easy to make mistakes .
- Macro calls are always marked with an exclamation point , Not easy to be ignored .
- Rust Macros will never insert mismatched square brackets or parentheses .
- Rust Macro built-in pattern matching , Easy to maintain and extend .
18.1 - Macro Foundation
macro_rules!
yes Rust The main way of defining macro .marcro_rule! assert_eq { ($left: expr, $right: expr) => ( // Pattern { // Templates match (&$left, &$right) { if !(*left_val == *right_val) { panic!("assertion failed: '(left == right)' \ (left: '{:?}', right: '{:?}')", left_val, right_val) } } } ); }
- Note that in the above code
assert_eq
There is no exclamation point behind . - Exclamation marks are required only when calling macros
!
, When defining, you don't need .
- Note that in the above code
file!
、line!
andmacro_rules!
, Itself is built into the compiler .Another way of macro definition : Procedure macro (procedural macro).
macro_rule!
The macro defined is completely based on the pattern matching implementation logic .( Pattern 1 ) => ( Templates 1 ); ( Pattern 2 ) => ( Templates 2 ); ...
You can use parentheses around patterns and templates , Use square brackets or curly braces .
The following forms are equivalent :
assert_eq!(gcd(6, 10), 2); assert_eq![gcd(6, 10), 2]; assert_eq!{ gcd(6, 10), 2} // When using curly braces , The last semicolon is optional .
Usage conventions or conventions of brackets :
- Calling
assert_eq!
when , Use parentheses - Calling
vec!
Use square brackets - Calling
macro_rules!
Use curly braces
- Calling
18.1.1 - Macro Extension Foundation
You cannot call a macro before defining it ,Rust Macro calls are analyzed and extended .
Macro mode operates on tokens (token), Such as digital 、 name 、 Punctuation, etc Rust Grammatical symbols of programs . Notes and whitespace are not notations .
For
$left:expr
The meaning of :
expr
Is an expression , Its value will be assigned to$left
.- Macro patterns are the same as regular expressions , Only a few special characters trigger special matching behavior .
- Other characters , Like a comma , Need to match literally , Otherwise, matching will fail .
18.1.3 - repeat
The standard
vec!
There are two forms of macros :// Repeat a value N Time let buffer = vec![0_u8; 1000]; // A comma separated list of values let numbers = vec!["udon", "ramen", "soba"];
vec!
Implementation of macro :macro_rules! vec { ($elem: expr; $n: expr) => { ::std::vec::from_elem($elem, $n) }; ( $( $x:expr ),* ) => { <[_]>::into_vec(Box::new([ $( $x ),* ])) }; ( $( $x:expr ),+ ,) => { vec![ $( $x ),* ] }; }
Repetitive patterns :
Pattern meaning $( ... )*
matching 0 Or many times , There is no separator $( ... ),*
matching 0 Or many times , Separated by commas $( ... );*
matching 0 Or many times , Semicolon separated $( ... )+
matching 1 Or many times , There is no separator $( ... ),+
matching 1 Or many times , Separated by commas $( ... );+
matching 1 Or many times , Semicolon separated $x
Is a set of expressions ;<[_]>
A slice that represents a certain type of value .,
Indicates matching a list with extra commas .
18.2 - Built in macro
file!()
: Expand to a string literal , The current file name .line!()
: Expand to au32
Literal , Represents the current line ( from 1 Start )column!()
: Expand to au32
Literal , Represents the current column ( from 0 Start )stringify!(...tokens...)
: Expand to a string literal , Contains the given token .assert!
Use this built-in macro to generate an error message containing assertion code .- If the parameter contains a macro , Then there will be no expansion , Such as
stringify(line!())
, Any parameter is a string"line!()"
.
concat!(str0, str1, ...)
: Expand to a string literal , Is the result of splicing its parameters .cfg!(...)
: Expand to a Boolean constant , If the current build configuration matches the conditions in parentheses , Then fortrue
.env!("VAR_NAME")
: Expand to a string , That is, specify the value of the environment variable at compile time . If the specified variable does not exist , A compilation error occurs . Often withCargo
Use a combination of .option_env!("VAR_NAME")
: Andenv!
identical , But back toOption<&'static str>
, If the specified variable is not set , Then return toNone
.include!("file.rs")
: Expand to the contents of the specified file , Must be effective Rust Code , For example, the sequence of expressions or characteristic items .include_str!("file.txt")
: Expand to a&'static str
, Contains the text of the specified file .Usage method :
const COMPOSITOR_SHADER: &str = include_str!("../resources/compositor.glsl");
If the specified file does not exist , Or the text is not valid UTF-8, Causes a compilation error .
include_bytes!("file.dat")
: Extend the file as binary data . As a result,&'static [u8]
Type value .Rules for built-in macros :
- Processed at compile time , If the file does not exist or cannot be read , Then the compilation will fail .
- All macros cannot fail at run time .
- In any case , If the file name is a relative path , It will be parsed relative to the directory containing the current file .
18.3 - Debug macro
The process of macro expansion is invisible .
- Rust In the process of extending macros , When some errors are found, an error message will be printed .
- But the fully extended code with errors will not be displayed .
rustc
It can show the information of the code after extending all macros .
cargo build --verbose
You can seeCargo
How to callrustc
.- That is, copy
rustc
command , Add again-Z unstable-options --pretty expanded
Options .
log_syntax!()
macro : At compile time , Its parameters can be printed to the terminal .
- Can be used to implement similar
println!
Debugging of . - It is required to have
#![feature(log_syntax)]
Characteristic marks .
- Can be used to implement similar
Give Way Rust The compiler prints the logs of all macro calls to the terminal .
- Insert... Somewhere in the code
trace_macros!(true);
. - such ,Rust Each macro expanded , Will print the name and parameters of the macro .
- Insert... Somewhere in the code
18.4 - Customize a macro ——json!
macro
To develop a json!
macro , Receive one JSON
Value as parameter , Then expand it to something like the following Rust expression :
let students = json!([
{
"name": "Jim Blandy"
"class_of": 1926
"major": "Tibetan throat singing"
},
]);
18.4.1 - Fragment type
macro_rules!
Fragment types supported by macros :Fragment type matching ( Example ) You can add … expr
expression : 2 + 2, "udon", x.len()
=> , ;
stmt
Expression or declaration , Do not include the semicolon at the end ( priority of use expr
orblock
)=> , ;
ty
type : String
、Vec<u8>
、(&str, bool)
=> , ; =
path
route : ferns
、::std::sync::mpsc
=> , ; =
pat
Pattern : _
、Some(ref x)
=> , =
item
Characteristic item : struct Point {x: f64, y: f64}
、mod ferns;
There is no limit block
Code block : s += "ok\n"; true
There is no limit meta
Attribute body : inline
、derive(Copy, Clone)
、doc="3D models."
There is no limit ident
identifier : std
、Json
、longish_variable_name
There is no limit tt
Token tree : ;
、>=
、{}
、[0 1 (+ 0 1)]
There is no limit json!
The definition of macro is as follows :macro_rules! json { (null) => { Json::Null }; ([ $( $element:tt ),* ]) => { Json::Array(...) }; ({ $( $key:tt : $value:tt ),* }) => { Json::Object(...) }; ($other:tt) => { ... // TODO: return Number、String or Boolean }; }
18.6 - transcend macro_rules!
- Procedure macro :
- Support extended
#[derive]
attribute , To handle custom features . - As Rust Function implementation , Not a declarative rule set .
- Support extended
See 《Rust Programming 》( Jim - Brandy 、 Jason, - By orendov , Translated by lisongfeng ) Chapter 20
Original address
边栏推荐
- Deno介绍
- Getting started with applet cloud development - getting user search content
- Derivation of anti Park transform and anti Clarke transform formulas for motor control
- Mysqldump data backup
- 深入刨析的指针(题解)
- 如何做好功能测试
- NR modulation 1
- 【SLAM】lidar-camera外参标定(港大MarsLab)无需二维码标定板
- Game theory matlab
- How to write compile scripts compatible with arm and x86 (Makefile, cmakelists.txt, shell script)
猜你喜欢
MySQL Server层四个日志
Redo file corruption repair
Selenium share
Jenkins basic knowledge ----- detailed explanation of 03pipeline code
11. Container with the most water
Safety science to | travel, you must read a guide
【指针训练——八道题】
C # create self host webservice
[risc-v] external interrupt
The next industry outlet: NFT digital collection, is it an opportunity or a foam?
随机推荐
[ruoyi] set theme style
Python implementation of maddpg - (1) openai maddpg environment configuration
Analyze menu analysis
Software design principles
XSS challenges bypass the protection strategy for XSS injection
Idea push rejected solution
How to write compile scripts compatible with arm and x86 (Makefile, cmakelists.txt, shell script)
Performance test method of bank core business system
数据分析——seaborn可视化(笔记自用)
Custom attribute access__ getattribute__/ Settings__ setattr__/ Delete__ delattr__ method
Prototype design
Analyze 菜单分析
Arabellacpc 2019 (supplementary question)
Performance analysis of user login TPS low and CPU full
手写数据库客户端
codeforces每日5題(均1700)-第六天
Restful style
Handwriting database client
真机无法访问虚拟机的靶场,真机无法ping通虚拟机
Derivation of anti Park transform and anti Clarke transform formulas for motor control