|
|
|
@ -98,7 +98,7 @@ temp_vec
|
|
|
|
|
|
|
|
|
|
有三种类型的过程宏(自定义派生(derive),类属性和类函数),不过它们的工作方式都类似。
|
|
|
|
|
|
|
|
|
|
当创建过程宏时,其定义必须位于一种特殊类型的属于它们自己的 crate 中。这么做出于复杂的技术原因,将来我们希望能够消除这些限制。使用这些宏需采用类似示例 19-29 所示的代码形式,其中 `some_attribute` 是一个使用特定宏的占位符。
|
|
|
|
|
创建过程宏时,其定义必须驻留在它们自己的具有特殊 crate 类型的 crate 中。这么做出于复杂的技术原因,将来我们希望能够消除这些限制。使用这些宏需采用类似示例 19-29 所示的代码形式,其中 `some_attribute` 是一个使用特定宏的占位符。
|
|
|
|
|
|
|
|
|
|
<span class="filename">文件名: src/lib.rs</span>
|
|
|
|
|
|
|
|
|
@ -112,9 +112,9 @@ pub fn some_name(input: TokenStream) -> TokenStream {
|
|
|
|
|
|
|
|
|
|
<span class="caption">示例 19-29: 一个使用过程宏的例子</span>
|
|
|
|
|
|
|
|
|
|
过程宏包含一个函数,这也是其得名的原因:“过程” 是 “函数” 的同义词。那么为何不叫 “函数宏” 呢?好吧,有一个过程宏是 “类函数” 的,叫成函数会产生混乱。无论如何,定义过程宏的函数接受一个 `TokenStream` 作为输入并产生一个 `TokenStream` 作为输出。这也就是宏的核心:宏所处理的源代码组成了输入 `TokenStream`,同时宏生成的代码是输出 `TokenStream`。最后,函数上有一个属性;这个属性表明过程宏的类型。在同一 crate 中可以有多种的过程宏。
|
|
|
|
|
定义过程宏的函数以 TokenStream 作为输入并生成 TokenStream 作为输出。 TokenStream 类型由包含在 Rust 中的 proc_macro crate 定义并表示令牌序列。 这是宏的核心:宏所操作的源代码构成了输入 TokenStream,宏产生的代码是输出 TokenStream。 该函数还附加了一个属性,用于指定我们正在创建的程序宏类型。 我们可以在同一个 crate 中拥有多种程序宏。
|
|
|
|
|
|
|
|
|
|
考虑到这些宏是如此类似,我们会从自定义派生宏开始。接着会解释与其他形式宏的微小区别。
|
|
|
|
|
让我们看看不同种类的程序宏。 我们将从一个自定义的派生宏开始,然后解释使其他形式不同的小差异。
|
|
|
|
|
|
|
|
|
|
### 如何编写自定义 `derive` 宏
|
|
|
|
|
|
|
|
|
|