Do you remember how many holes we dug together ? Um. … I don't remember it myself , Today we'll dig another special pit , This pit can be said to be dug to the root —— meta-programming .

Metaprogramming is an important concept in the field of programming , It allows programs to treat code as data , Modify or replace code at run time . If you know Java, Do you think of it now Java Reflection mechanism of ? you 're right , It is a kind of metaprogramming .

<> reflex

Rust Reflection is also supported ,Rust Is reflected by the std::any::Any Package supported .

The following methods are provided in this package

TypeId yes Rust A type of , It is used to represent the unique identity of a type .type_id(&self) This method returns the TypeId.

is() Method is used to determine the type of a function .

You can take a look at its source code implementation
pub fn is<T: Any>(&self) -> bool { let t = TypeId::of::<T>(); let concrete =
self.type_id(); t == concrete }
As you can see, its implementation is very simple , It's contrast TypeId.

downcast_ref() and downcast_mut() Is a pair of T Method to convert to a specific type . Its return type is Option<&T> and Option<&mut
T>, in other words downcast_ref() Will type T Convert to immutable reference , and downcast_mut() take T Convert to variable reference .

Finally, we take an example to see how to use these functions .
use std::any::{Any, TypeId}; fn main() { let v1 = "Jackey"; let mut a: &Any; a
= &v1; println!("{:?}", a.type_id()); assert!(a.is::<&str>()); print_any(&v1);
let v2: u32 = 33; print_any(&v2); } fn print_any(any: &Any) { if let Some(v) =
any.downcast_ref::<u32>() { println!("u32 {:x}", v); } else if let Some(v) =
any.downcast_ref::<&str>() { println!("str {:?}", v); } else {
println!("else"); } }
<> macro

Rust The function provided by the reflection mechanism of is relatively limited , however Rust Macros are also provided to support metaprogramming .

up to now , Macro is a familiar and unfamiliar concept for us , It's familiar because we use it all the time println! macro , Strangeness is because we have never introduced it in detail .

about println! macro , Our intuitive sense of use is that it's similar to a function . But there are some differences between them .

We know that for functions , It receives a fixed number of parameters , And it is fixed when the function is defined . The number of parameters received by a macro is not fixed .

Here we talk about the macro is a function like macro , in addition ,Rust Another type of macro is a property like macro . It's kind of like Java Notes in , It is usually written above the function name as a tag .
#[route(GET, "/")] fn index() {
route This is used to specify interface methods , For this service , Root path GET Requests are routed to this index Function . Such a macro is passed through a procedure macro , Its definition uses
#[proc_macro_attribute] annotation . The annotation used in the definition of a procedure macro similar to a function is #[proc_macro].

In addition to the procedure macro , Another big category of macros is called declarative macros . Declaring a macro is done by macro_rules! To declare the defined macro , It is more widely used than procedure macro . We've been in contact with vec!
It is a kind of declaration macro . It is defined as follows :
#[macro_export] macro_rules! vec { ( $( $x:expr ),* ) => { { let mut temp_vec
= Vec::new(); $( temp_vec.push($x); )* temp_vec } }; }
Let's define a macro of our own .

Custom macro needs to use derive annotation .( Examples from the book)

Let's start by creating a hello_macro Of lib library , Define only one trait.
pub trait HelloMacro { fn hello_macro(); }
Then create a subdirectory hello_macro_derive, stay hello_macro_derive/Cargo.toml Add dependency to file
[lib] proc-macro = true [dependencies] syn = "0.14.4" quote = "0.6.3"
And then you can hello_macro_derive/lib.rs The function of defining our custom macro in the file is implemented .
extern crate proc_macro; use crate::proc_macro::TokenStream; use quote::quote;
use syn; #[proc_macro_derive(HelloMacro)] pub fn hello_macro_derive(input:
TokenStream) -> TokenStream { // Construct a representation of Rust code as a
syntax tree // that we can manipulate let ast = syn::parse(input).unwrap(); //
Build the trait implementation impl_hello_macro(&ast) } fn
impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream { let name =
&ast.ident; let gen = quote! { impl HelloMacro for #name { fn hello_macro() {
println!("Hello, Macro! My name is {}", stringify!(#name)); } } }; gen.into() }
Two are used here crate:syn and quote, among syn It's a Rust Code conversion into a special operational data structure , and quote But the effect of this is just the opposite .

You can see , The annotations we use for custom macros are #[proc_macro_derive(HelloMacro)]
, among HelloMacro Is the name of the macro , when in use , We just need to use annotations #[derive(HelloMacro)] that will do .

We should introduce these two dependencies first
hello_macro = { path = "../hello_macro" } hello_macro_derive = { path =
"../hello_macro/hello_macro_derive" }
Then use it again
use hello_macro::HelloMacro; use hello_macro_derive::HelloMacro;
#[derive(HelloMacro)] struct Pancakes; fn main() { Pancakes::hello_macro(); }
Running results show that , We can successfully capture the structure name in the implementation .

<> summary

In this paper, we have introduced Rust Two kinds of meta programming for : Reflections and macros . The function provided by reflection is weak , But the power of macros is very powerful . What we're talking about about macro is just a scratch , To really understand macros , More time is needed to learn .

Technology
©2019-2020 Toolsou All rights reserved,
Share has surpassed Ningde Era !LG Chemical confirmation to spin off battery business unit Programmer and architect Hua Shan springboot Multi profile configuration el-ui:select Get value Science fiction comes true !“ Trisomy ” Found out common 5 species JAVA Runtime exception git Pull the remote branch and switch to it Redis Counter High concurrency applications Java Thread of Sleep() Summary of usage Front end to background 5 Summary of different ways