[][src]Function tao_of_rust::ch12::macros::declarative_macros

pub fn declarative_macros()

宏系统: 声明宏

Basic usage:

macro_rules! unless {
    ($arg:expr, $branch:expr) => ( if !$arg { $branch };); 
} 
fn cmp(a: i32, b: i32) {
    unless!( a > b, {
        println!("{} < {}", a, b);
    });
}
fn main() {
   let (a, b) = (1, 2);
   cmp(a, b);
}Run

Basic usage: 使用宏2.0语法,定义unless!宏

#![feature(decl_macro)]
 
macro unless($arg:expr, $branch:expr) {
    ( if !$arg { $branch }); 
} 
fn cmp(a: i32, b: i32) {
    unless!( a > b, {
        println!("{} < {}", a, b);
    });
}
fn main() {
   let (a, b) = (1, 2);
   cmp(a, b);
}Run

Basic usage: 如何实现hashmap!宏 V1.0

使用

cargo rustc -- -Z unstable-options --pretty=expanded

rustc -Z unstable-options --pretty=expanded main.rs

命令查看宏展开代码

 
macro_rules! hashmap {
    ($($key:expr => $value:expr),* ) => {
        {
            let mut _map = ::std::collections::HashMap::new();
            $(  
                _map.insert($key, $value); 
            )*
            _map
        }
    };
}
fn main(){
    let map = hashmap!{
        "a" => 1,
        "b" => 2
      //  "c" => 3, // V1.0不支持结尾有逗号
    };
    assert_eq!(map["a"], 1);
}Run

Basic usage: V2.0 - hashmap!递归调用消去最后键值对的结尾逗号

macro_rules! hashmap {
    ($($key:expr => $value:expr,)*) =>
        {  hashmap!($($key => $value),*) };
    ($($key:expr => $value:expr),* ) => {
        {
            let mut _map = ::std::collections::HashMap::new();
            $(
                _map.insert($key, $value);
            )*
           _map
       }
   };
}
fn main(){
    let map = hashmap!{
        "a" => 1,
        "b" => 2,
        "c" => 3, 
    };
    assert_eq!(map["a"], 1);
}Run

Basic usage: V3.0 - 利用重复匹配规则

macro_rules! hashmap {
    ($($key:expr => $value:expr),* $(,)*) => {
        {
            let mut _map = ::std::collections::HashMap::new();
            $(
                _map.insert($key, $value);
            )*
            _map
        }
   };
}
fn main(){
    let map = hashmap!{
        "a" => 1,
        "b" => 2,
        "c" => 3, 
    };
    assert_eq!(map["a"], 1);
}Run

Basic usage: V4.0 - 如何为hashmap!宏添加根据给定的键值对数量预分配空间的功能?

macro_rules! unit {
    ($($x:tt)*) => (());
}
macro_rules! count {
    ($($key:expr),*) => (<[()]>::len(&[$(unit!($key)),*]));
}
macro_rules! hashmap {
    ($($key:expr => $value:expr),* $(,)*) => {
        {
           let _cap = count!($($key),*);
           let mut _map 
               = ::std::collections::HashMap::with_capacity(_cap);
           $(
               _map.insert($key, $value);
           )*
           _map
       }
   };
}
fn main(){
   let map = hashmap!{
       "a" => 1,
       "b" => 2,
       "c" => 3, 
   };
   assert_eq!(map["a"], 1);
}Run

Basic usage: V5.0 - 重构V4.0版hashmap!宏,消除外部宏unit!和count!

macro_rules! hashmap {
    (@unit $($x:tt)*) => (());
    (@count $($rest:expr),*) => 
        (<[()]>::len(&[$(hashmap!(@unit $rest)),*]));
    ($($key:expr => $value:expr),* $(,)*) => {
        {
            let _cap = hashmap!(@count $($key),*);
            let mut _map = 
                ::std::collections::HashMap::with_capacity(_cap);
           $(
               _map.insert($key, $value);
           )*
           _map
       }
   };
}
fn main(){
   let map = hashmap!{
       "a" => 1,
       "b" => 2,
       "c" => 3, 
   };
   assert_eq!(map["a"], 1);
}Run

Basic usage: 使用#![feature(trace_macros)]特性调试hashmap!宏

#![feature(trace_macros)]
macro_rules! hashmap {
    (@unit $($x:tt)*) => (());
    (@count $($rest:expr),*) => 
        (<[()]>::len(&[$(hashmap!(@unit $rest)),*]));
    ($($key:expr => $value:expr),* $(,)*) => {
        {
            let _cap = hashmap!(@count $($key),*);
            let mut _map = 
                ::std::collections::HashMap::with_capacity(_cap);
           $(
               _map.insert($key, $value);
           )*
           _map
       }
   };
}
fn main(){
   trace_macros!(true);
   let map = hashmap!{
       "a" => 1,
       "b" => 2,
       "c" => 3, 
   };
   assert_eq!(map["a"], 1);
}Run

宏导入导出

请查阅源码中的相关crate