Rust 宏

前言

Rust 语言中的宏可以帮助你实现动态生成代码和简化代码的工作。以下是一个简单的示例,展示了如何在 Rust 中使用宏:

示例

// Define a macro
macro_rules! hello_world {
    ($x:expr) => {
        println!("Hello, world! {}", $x);
    };
}

fn main() {
    // Call the macro with a variable
    hello_world!("一碗情深");
}

在这个例子中,我们定义了一个名为 hello_world 的宏。这个宏接受一个参数 $x.在 main 函数中,我们调用这个宏并传递了一个名为 “一碗情深” 的变量,并使用 println! 函数输出 “Hello, world! 一碗情深”。

需要注意的是,宏是由 macro_rules! 关键字定义的,宏的名称后面是它的形式(即 ($x:expr) => {...}),接下来跟着要被替换的表达式,最后是冒号、花括号和表达式。在上面的例子中,宏 hello_world 将在后面的所有地方被替换为 println!("Hello, world! {}", $x);

简而言之,宏是一种机制,用于在编译时创建和执行代码,而不需要像其他语言(如 JavaScript,Python 等)那样在运行时编译代码。这在一些情况下非常有用,比如模板引擎、解析和生成代码等。

宏定义的语法允许在支持的标识符和操作符之间自由组合。除了像 expr 这样的标识符之外,你还可以将其他标识符(如 identliteralmatch 等)用于宏定义:例如,你可以在宏定义中使用 const 关键字:

macro_rules! hello_world_const {
    ($x:const String) => {
        println!("Hello, world! {}", $x);
    };
}

在这个例子中,$x:const String 是一个名为 String 的 Rust const 类型。const 关键字告诉我们,这个表达式的值在编译时是不可更改的。在宏调用 hello_world_const!(一碗情深) 中,“一碗情深” 的类型和值都保持不变。这使得我们可以像使用普通变量一样使用常量类型,而不必担心意外更改其值。

实战

新建 macros.rs 文件,写入以下代码:

#[allow(unused_macros)]
#[macro_export]
macro_rules! hashmap {
    ($( $key: expr => $val: expr ),*) => {{
         let mut map = ::std::collections::HashMap::new();
         $( map.insert($key, $val); )*
         map
    }}
}

#[allow(unused_macros)]
#[macro_export]
macro_rules! hashmap_s {
    ($( $key: expr => $val: expr ),*) => {{
         let mut map = ::std::collections::HashMap::new();
         $( map.insert($key.to_string(), $val); )*
         map
    }}
}

#[macro_export]
macro_rules! vec_s {
    ($( $val: expr ),*) => {{
        let mut vec = ::std::vec::Vec::new();
        $( vec.push($val.to_string()); )*
        vec
    }}
}

#[macro_export]
macro_rules! hashset {
    ($( $val: expr ),*) => {{
        let mut vec = ::std::collections::HashSet::new();
        $( vec.insert($val); )*
        vec
    }}
}

#[macro_export]
macro_rules! hashset_s {
    ($( $val: expr ),*) => {{
        let mut vec =  ::std::collections::HashSet::new();
        $( vec.insert($val.to_string()); )*
        vec
    }}
}

main.rs 调用宏:

use std::collections::{HashSet, HashMap};

#[macro_use]
pub mod macros;

fn main() {
    let my_vec: Vec<String> = vec_s!["点个赞", "关注我", "一碗情深"];
    println!("my_vec: {:?}", my_vec);
    
    let my_hashset: HashSet<&str> = hashset!["只能保存不同的值", "一样的值试试", "一样的值试试", "hashset宏数只能存入一种类型"];
    println!("my_hashset: {:?}", my_hashset);

    let my_hashset_num: HashSet<i32> = hashset![1,3,3,4];
    println!("my_hashset_num: {:?}", my_hashset_num);

    let my_hashset_s: HashSet<String> = hashset_s!["只能保存不同的值", "一样的值试试", "一样的值试试", "hashset_s宏数字会转成String", 2];
    println!("my_hashset_s: {:?}", my_hashset_s);
    
    let my_hashmap: HashMap<i32, (&str, bool)> = hashmap![
        1 => ("一样的key会覆盖", true),
        2 => ("文本2", false),
        1 => ("一样的key会覆盖", false)
    ];
    println!("my_hashmap: {:?}", my_hashmap);
}

运行结果:
my_vec: [“点个赞”, “关注我”, “一碗情深”]
my_hashset: {“只能保存不同的值”, “一样的值试试”, “hashset宏数只能存入一种类型”}
my_hashset_num: {3, 4, 1}
my_hashset_s: {“只能保存不同的值”, “一样的值试试”, “hashset_s宏数字会转成String”, “2”}
my_hashmap: {2: (“文本2”, false), 1: (“一样的key会覆盖”, false)}

在Rust编程语言中,#[allow(unused_macros)] 宏是一种编译器选项,它用来让你的Rust代码忽略特定的未使用的宏。

注意,Rust并未滥用编译时生命周期或者未使用的函数检查。这些特性的存在是为了帮助开发者写出安全的、不易出错的代码。当你使用未使用的宏时,这些特性可能无法正常工作,因为Rust无法知道这些宏何时被使用,或者它们的改动是否有可能在未来的代码中导致问题。

#[allow()] 宏用来告诉编译器,即使代码中出现违反规则的地方,也不要报错。在Rust中,描述未使用宏的规则很长,所有未被使用的宏都会被视为违反规则,这可能导致编译错误。当在一个 #[allow()] 标签内使用没有定义的宏时,这将不会引发错误。

#[allow(unused_macros)] 宏在你希望在代码中忽略某些全局的宏或者类型系统层面的宏时特别有用。因为在某些情况下,这些宏可能会因为可能的错误而导致代码不能正常执行。

在Rust语言中,#[macro_export] 是一个定义扩展宏的特殊标识。扩展宏是一种特殊类型的宏,它们可以在Rust标准库和第三方库中使用。它们适用于在代码中需要实现私有宏但又需要定义公共API的情况。

宏的主要目的是重用代码和实现可移值代码。我们可以在模块(例如 lib.rs)中定义私有宏,然后在其他模块(lib_a.rs,lib_b.rs等)中使用这些公共宏的实例。

你可以使用上述代码来定义一个只需要定义一次的类的公共API,而不需要为每个需要使用这个API的模块都定义一个新的函数。你的模块共享这些宏的定义,而不需要在每个模块中都包含这个公共宏的定义。

注:在Rust中,宏引入了很多抽象层,包括缩进(A和B宏都有相同的书写顺序,但A宏的作用会影响到B宏的作用)、marshalling和unmarshalling。因此,使用宏时需要特别小心,以避免出现预期之外的行为或错误。如果你不熟悉宏的工作原理,可能需要深入学习Rust的宏和其他高级特性,以避免编写出无法发现的错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Rust权威指南是一本深入介绍Rust编程语言的权威性书籍。这本书主要介绍Rust语言的基本语法和特性,包括Rust的所有关键字、数据类型、函数、模块、、”生命周期”、所有权等重要概念的详细解释和使用方法。 这本书由Rust社区知名的开发者Steve Klabnik和Carol Nichols撰写,是Rust开发者及其他想要学习Rust编程语言的程序员的必读之作。书中详细介绍了Rust的语法规则和特性,如何编写高质量、高性能的Rust代码,以及如何使用Rust来进行并发编程和系统级编程。 通过阅读本书,读者能够了解Rust的核心概念,如所有权、生命周期和借用,以及如何使用Rust的工具链进行开发。在本书的后半部分,作者通过实践案例和示例向读者展示了如何使用Rust来编写高效、可靠的程序。 总的来说,Rust权威指南是一本非常实用且详尽的Rust编程语言指南,对于想要学习Rust编程语言的读者非常有益。不仅提供了基础知识方面的介绍,还给读者提供了诸如性能优化等高级内容的指导。同时,本书也适合那些已经有一定Rust编程经验的读者,它们可以通过本书深入了解Rust语言内部之间的联系。 ### 回答2: 《Rust权威指南》是一本针对Rust编程语言的详细讲解和指导的权威指南。该书由Rust的核心开发人员编写,涵盖了Rust语言的基本概念、语法、数据类型、内存管理、并发编程、错误处理、泛型、等方面,旨在帮助读者全面深入地学习和理解Rust语言。 该书内容广泛,详细全面,适合初学者和有经验的开发人员。书中每一章都有大量的代码示例,并附有解释和注释,易于理解。书中还介绍了Rust的生态系统和常用开发工具,如包管理器Cargo、测试框架等。 此外,《Rust权威指南》还强调了Rust语言的安全性和性能优势。Rust通过静态类型检查、所有权系统、借用规则等机制,大大减少了程序运行时的内存安全问题。同时,Rust的设计和实现也使得其具有与C++类似的性能优势。 总的来说,《Rust权威指南》是一本权威性强、内容深入的Rust编程指南。对于想要学习Rust编程语言的开发人员来说,这本书绝对是一本值得购买和阅读的好书。 ### 回答3: 《Rust权威指南》是一本全面介绍Rust语言的书籍,该书由Rust中文社区的翻译小组翻译而成。这本书详细讲解了Rust语言的语法、基础知识、数据类型、控制流、函数、模块、生命周期、所有权系统等内容,涵盖了Rust语言的各个方面。 这本书的特点在于其权威性和全面性。作为Rust语言的权威指南,该书不仅涵盖了Rust语言的基础知识,还深入讲解了Rust语言的高级特性,如内存管理、安全性、并发等方面。此外,书中还包括了大量的实例和案例,可以帮助读者更深入地理解Rust语言。 对于初学者来说,该书可以作为Rust语言的入门指南。对于已经掌握了Rust语言基础知识的读者来说,本书也可以作为进一步深入学习和实践Rust语言的指南。此外,该书还提供了完整的API文档和Rust语言的标准规范,方便读者进行参考和查阅。 总之,《Rust权威指南》是一本全面、详细、权威的Rust语言指南,适合Rust语言的初学者和进阶者。读者可以通过该书深入了解Rust语言并掌握其应用,提高自己的编程能力和实践经验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一碗情深

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值