当前位置:网站首页>[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
边栏推荐
- Arabellacpc 2019 (supplementary question)
- Leetcode problem solving -- 108 Convert an ordered array into a binary search tree
- 出现Permission denied的解决办法(750权限谨慎使用)
- js凡客banner轮播图js特效
- MySQL advanced notes
- Idea push rejected solution
- SAP ALV颜色代码对应颜色(整理)
- Redo file corruption repair
- What are the principles of software design (OCP)
- Sign SSL certificate as Ca
猜你喜欢
How to do function test well
IPv6 comprehensive experiment
Research on cooperative control of industrial robots
[unity3d] GUI control
八道超经典指针面试题(三千字详解)
[Li Kou] the second set of the 280 Li Kou weekly match
Explore pointers and pointer types in depth
Mysqldump data backup
暑期刷题-Day3
BUUCTF刷题笔记——[极客大挑战 2019]EasySQL 1
随机推荐
Restful style
SWC介绍
Microsoft Research, UIUC & Google research | antagonistic training actor critic based on offline training reinforcement learning
深入探究指针及指针类型
Deno介绍
SAP ALV颜色代码对应颜色(整理)
【概念】Web 基础概念认知
JS音乐在线播放插件vsPlayAudio.js
Yyds dry inventory what is test driven development
Some problem records of AGP gradle
多态day02
IPv6 jobs
Idea push rejected solution
SD card reports an error "error -110 whilst initializing SD card
Research on cooperative control of industrial robots
[ruoyi] ztree custom icon (iconskin attribute)
Self made CA certificate and SSL certificate using OpenSSL
NR modulation 1
SAP ALV单元格级别设置颜色
Redis cache breakdown, cache penetration, cache avalanche