a.rust宏.txt

/*

更多请看:
http://blog.hubwiz.com/2020/01/30/rust-macro/
https://github.com/rooat/RustLearn/blob/master/src/appendix-04-macros.md
https://rustcc.gitbooks.io/rustprimer/content/macro/macro.html
https://rust-by-example.budshome.com/macros.html

定义:Rust宏让你可以发明自己的语法,编写出可以自行展开的代码,也就是我们通常所说的元编程,你甚至可以用Rust宏来创作自己的DSL。
    从根本上来说,宏是一种为写其他代码而写代码的方式,即所谓的元编程

运作机制:首先匹配宏规则中定义的模式,然后将匹配 结果绑定到变量,最后展开变量替换后的代码。

调用方式:另外从形式上看,与函数调用的另一个区别是参数可以用圆括号(())、花括号({})、方括号([])中的任意一种括起来,
        比如这行也可以写成 println!["Hello, world!"] 或 println!{"Hello, world!"},不过对于 Rust 内置的宏都有约定俗成的括号,
        比如 vec! 用方括号,assert_eq! 用圆括号

宏的分类:
声明式宏( declarative macro )来进行元编程(metaprogramming)
过程式宏( procedural macro )来自定义 derive traits

() => {}看起来很神秘,因为它不是标准的rust语法,是macro_rules! 这个宏自己发明的,用来表示一条宏规则,=>左边是匹配模式,右边是 等待展开的代码

rust 有哪些自带宏? 
源文件 std/src/macros.rs
panic print println eprint eprintln dbg assert_approx_eq debug_assert debug_assert_eq debug_assert_ne matches r#try write writeln unreachable unimplemented todo compile_error format_args format_args_nl env option_env concat_idents concat line column file stringify include_str include_bytes 
module_path cfg include assert asm llvm_asm global_asm log_syntax trace_macros
源文件 alloc/src/macros.rs 
vec format

Rust自带的声明宏:
常用的宏函数:assert, cfg, dbg, env, format, eprintln, println, panic, vec。
-------------------------------------------------------------------------------

宏导入导出用 #[macro_use] 和 #[macro_export]。父模块中定义的宏对其下的子模块是可见的,要想子模块中定义的宏在其后面的父模块中可用,需要使用 #[macro_use]。

*/

use std::collections::HashMap;

//-----------------------通用元编程的声明式宏 macro_rules!-------------------------

//一个空的宏
macro_rules! hey{
     () => {}
}

//可以定义多条宏规则  感觉就像函数重载
macro_rules! hey2{
     () => {};
     () => {}
}

//其中name可以更改名字 expr不可更改
macro_rules! yo{
     ($name:expr) => {
          println!("Yo {}!",$name);
     }
}

//函数可以打印自己的名字
macro_rules! create_function {
     ($func_name:ident) => (
         fn $func_name() {
             println!("function {:?} is called", stringify!($func_name))
         }
     )
}
 
//多参数的宏
macro_rules! hey3{
     ($($name:expr),*) => {}
}

//输入源是成对出现的 =>写法是宏规则定的,不可更改
macro_rules! hey4{
     ($($key:expr => $value:expr), *) => {{
          let mut map = HashMap::new();
          $(map.insert($key, $value);) *
          map
     }}
}

//看一个 vec! 稍微简化的定义
//注意:标准库中实际定义的 vec! 包括预分配适当量的内存。这部分为代码优化,为了让示例简化,此处并没有包含在内。
#[macro_export]
macro_rules! vec {
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
            )*
            temp_vec
        }
    };
}

//-----------------------自定义 derive 的过程式宏-------------------------
extern crate hello_macro;
#[macro_use]
extern crate hello_macro_derive;

use hello_macro::HelloMacro;

#[derive(HelloMacro)]
struct Pancakes;

/* 
hello_macro_derive存在的意义:其实我们完全不用hello_macro_derive也可以实现类似功能
然而,他们需要为每一个他们想使用 hello_macro 的类型编写实现的代码块。我们希望为其节约这些工作。
另外,我们也无法为 hello_macro 函数提供一个能够打印实现了该 trait 的类型的名字的默认实现:Rust 没有反射的能力,因此其无法在运行时获取类型名。我们需要一个在运行时生成代码的宏。

extern crate hello_macro;
use hello_macro::HelloMacro;
struct Pancakes;
impl HelloMacro for Pancakes {
    fn hello_macro() {
        println!("Hello, Macro! My name is Pancakes!");
    }
}
*/
fn main() {

    //-----------------------通用元编程的声明式宏 macro_rules!-------------------------
     hey!();

     yo!("666666666666");
     yo!["666666666666"];
     yo!{"666666666666"};
     //yo!<"666666666666">; 前三种写法都是正确的,唯独这个不行

     create_function!(foo);
     foo();

     hey3! ("Finn", "Jake", "PB");

     let user = hey4! (
          "liujiayu" => 30,
          "liuyalin" => 31
     );
     println!("user {:?}",user);

     //-----------------------自定义 derive 的过程式宏-------------------------
     Pancakes::hello_macro();
}

/*
-----------------------自定义 derive 的过程式宏依赖-------------------------
本包toml:
[dependencies]
hello_macro = { path = "./hello_macro" }
hello_macro_derive = { path = "./hello_macro/hello_macro_derive" }
------------------------------------------------------------------------------------
hello_macro包lib.rs:
/*
对于一个 foo 的包来说,一个自定义的派生过程式宏的包被称为 foo_derive
*/
pub trait HelloMacro {
    fn hello_macro();
}
----------------------------------------------------------------------------------
hello_macro_derive包lib.rs:
extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;

#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    // Construct a string representation of the type definition
    let s = input.to_string();

    // Parse the string representation
    let ast = syn::parse_derive_input(&s).unwrap();

    // Build the impl
    let gen = impl_hello_macro(&ast);

    // Return the generated impl
    gen.parse().unwrap()
}

fn impl_hello_macro(ast: &syn::DeriveInput) -> quote::Tokens {
    let name = &ast.ident;
    quote! {
        impl HelloMacro for #name {
            fn hello_macro() {
                println!("impl_hello_macro--->Hello, Macro! My name is {}", stringify!(#name));
            }
        }
    }
}
----------------------------------------------------------------------------------
hello_macro_derive包toml:
[lib]
proc-macro = true

[dependencies]
syn = "0.11.11"
quote = "0.3.15"

*/

 

上一篇:fiddler弱网环境设置


下一篇:关于计划任务的一个小需求-实现篇