Rust学习2-宏与元编程
2022-02-04-
什么是元编程
元编程是指某类[计算机程序]的编写,这类计算机程序编写或者操纵其他程序(或者自身)作为它们的数据,或者在[运行时]完成部分本应在[编译时]完成的工作。 元编程是用来产生代码的程序,操纵代码的程序,在运行时创建和修改代码而非编程时,这种程序叫做元程序。而编写这种程序就叫做元编程。
元编程是一种编程技术,编写能够生产新代码的代码,根据语言的不同,实现的方式有两种: 在运行时编译和在编译期.
运行时元编程可用于动态语言: 例如python,JavaScript,Lisp.
编译型语言不可能在运行时生成指令,执行程序预编译.
Rust提供编译期代码生成功能,
Rust宏不会从执行环境中捕获变量
Rust中的宏及其类型
Rust宏时在抽象语法树构造的第二阶段结束时解析的, 进行名称解析的阶段, 名称解析时在作用域中查找在表达式中定义的变量是否存在的阶段.
Rust宏能够识别上下文,并根据宏扩展响应的内容,
常见的宏就是println!
, 允许我们向println
宏传递尽可能多的参数. Rust不支持传递函数的可变参数.
println!("{}", 1); // 默认用法,打印Display println!("{:o}", 9); // 八进制 println!("{:x}", 255); // 十六进制 小写 println!("{:X}", 255); // 十六进制 大写 println!("{:p}", &0); // 指针 println!("{:b}", 15); // 二进制 println!("{:e}", 10000f32); // 科学计数(小写) println!("{:E}", 10000f32); // 科学计数(大写) println!("{:?}", "test"); // 打印Debug println!("{:#?}", ("test1", "test2")); // 带换行和缩进的Debug打印 输出非基本类型的类JSON格式的值 println!("{a} {b} {b}", a = "x", b = "y"); // 命名参数
宏的类型
- 声明宏(Declarative Macro) 使用
macro_rules!
宏创建 - 过程宏(Procedural Macro) 更高级形式,完全控制代码的操作和生成.
声明宏(Declarative Macro)和过程宏(Procedural Macro)。前者指的是用某种语法直接声明出的宏。后者是对应直接生成抽象语法树的过程的宏。直觉上过程宏更隐式,更全能;声明宏更可读,更直接。
编写一个声明宏,实例:
use std::io;
// 定义一个输入宏
macro_rules! scanline {
($x:expr) => {
io::stdin().read_line(&mut $x).unwrap();
};
}
fn main() {
let mut input = String::new();
scanline!(input);
println!(" read {:?}",input);
}
过程宏(Procedural Macro):
- 自定义
#[derive]
宏在结构体和枚举上指定通过derive
属性添加的代码,在函数上使用#[proc_macro_derive]
属性, - 类属性(Attribute-like)宏定义可用于任意项的自定义属性, 在函数上使用
#[proc_macro_attribute]
属性, - 类函数宏看起来像函数不过作用于作为参数传递的 token, 在函数上使用
#[proc_macro]
属性,
标准库中的内置宏
dbg!
: 允许使用他们的值输出表达式的值compile_error!
: 在编译期从代码中报告错误.concat!
链接传递给它的任意数量的文字, 并将链接的文字作为&'static str
返回env!
: 检查编译期的环境变量, 安全版本的宏为 :option_env!
eprint!
和eprintln!
与println!
类型, 将消息输出到标准异常流中include_bytes!
: 作为一种将文件读取为字节数组的快捷方式,stringify!
: 获得类型或标记作为字符串的字面转换vec!
: vector