Rust 1.30 带来更多元编程支持,并改进了模块系统

阅读数:928 2018 年 11 月 15 日

Rust 的最新版本1.30扩展了过程宏,允许它们定义新的属性和类似于函数的宏。此外,它简化了 Rust 模块系统,使其更加一致、直观。

Rust 1.30 引入了两种新类型的过程宏,“类属性的过程宏”和“类函数的过程宏”。过程宏是 Rust 元编程的基础,支持操作程序语法树。在这方面,过程宏要比声明宏强大得多,声明宏提供了一种机制来定义基于模式匹配的更复杂代码的简写。

类属性过程宏类似于现有的派生宏,但是更灵活,因为它们允许你创建新的属性,并且除了结构和枚举之外,还可以应用于函数。例如,一个属性宏可以实现 route 属性规范,定义 HTTP 路由:

复制代码
// 使用路由过程宏
#[route(GET, "/")]
fn index() {
...
}
// 过程宏定义路由
#[proc_macro_attribute]
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
// attr 接收 GET,宏的 "/" 部分
// item 接收 fn index () { ...
}

类似地,类函数过程宏允许你定义类似于函数的宏,例如:

复制代码
// 解析 SQL 语句
let sql = sql!(SELECT * FROM posts WHERE id=1);
#[proc_macro]
pub fn sql(input: TokenStream) -> TokenStream {

在这两个示例中,TokenStream 都表示应用属性的语法树或属性 / 函数定义。route/sql 函数将接收到的语法树转换为返回给调用者的新语法树,即生成要执行的新代码

在使用 Rust 模块系统时,Rust 1.30 还对 use 宏进行了一些修改,以提升开发人员的体验。首先,use 现在可以引入宏定义,从而淘汰了 macro_use 注解:

复制代码
// 旧:
#[macro_use]
extern crate serde_json;
// 新:
extern crate serde_json;
use serde_json::json;

此外,通过把所有对名称空间的引用都与 prelude 模块中包含的所有 extern crate 指令进行比较,并使用匹配的那个,使得外部 Crates 对于在模块层次结构中移动的函数具有更强的适应性。以前,必须显式地在模块内部使用 extern 或者使用::extern_name 语法,如下例所示:

复制代码
extern crate serde_json;
fn main() {
let json = serde_json::from_str("..."); // OK
}
mod foo {
// 为在模块种使用 serde_json,必须显式使用 use
use serde_json;
fn bar() {
let json = serde_json::from_str("...");
}
fn baz() {
// 也可以使用外部模块的完整限定名
let json = ::serde_json::from_str("...");
}

最后,use 现在以更加一致的方式解释模块路径。现在,你可以使用 crate 关键字来表明你希望模块路径从 crate 根路径开始。在 1.30 版本之前,这是默认的模块路径,但是,直接引用项的路径将从本地路径开始:

复制代码
mod foo {
pub fn bar() {
// ...
}
}
mod baz {
pub fn qux() {
// 旧
::foo::bar();
// 无效,这和使用“use”不同:
// foo::bar();
// 新
crate::foo::bar();
}
}

Rust 1.30 还带来了如下变化:

  • 你现在可以通过加上前缀 r# 把关键字作为标识符,例如 r#for。这种变化主要是因为 Rust 2018 将引入新的关键词,这样一种机制应当可以用于转换使用这些关键字作为变量或函数名的现有代码。
  • 借助 no_std,你现在可以构建应用程序而不使用标准库。以前,由于无法定义 panic_handler,所以你只能使用 no_std 构建库。

你可以使用 $ rustup update stable 更新 Rust 分发包。关于 Rust 1.30 的完整细节,请查阅发布说明

查看英文原文:Rust 1.30 Brings More Metaprogramming Support and Improved Modules

收藏

评论

微博

发表评论

注册/登录 InfoQ 发表评论