Helix-hashmap! 宏 解析

本贴最后更新于 325 天前,其中的信息可能已经事过境迁

hashmap!

#[macro_export] macro_rules! hashmap { (@single $($x:tt)*) => (()); (@count $($rest:expr),*) => (<[()]>::len(&[$(hashmap!(@single $rest)),*])); ($($key:expr => $value:expr,)+) => { hashmap!($($key => $value),+) }; ($($key:expr => $value:expr),*) => { { let _cap = hashmap!(@count $($key),*); let mut _map = ::std::collections::HashMap::with_capacity(_cap); $( let _ = _map.insert($key, $value); )* _map } }; }
  1. 宏属性

    • #[macro_export]​:这个属性使得宏可以在定义它的 crate 外部使用。
  2. 内部辅助宏

    • (@single $($x:tt)*) => (());​:这是一个内部宏规则,它匹配任何 Token 树(tt​)并返回一个空元组。这个规则似乎没有实际作用,可能是为了占位或调试。
    • (@count $($rest:expr),*) => (<[()]>::len(&[rest)),*]));​:这是另一个内部宏规则,用于计算宏调用中提供的表达式数量。它通过生成一个元组数组并计算其长度来实现。
  3. 外部宏规则

    • (key:expr => (value),+) };​:这个规则处理以逗号结尾的键值对列表。它是一个重复规则,允许宏调用者提供多个键值对。
    • (key:expr => $value:expr),*) => { ... };​:这个规则处理不以逗号结尾的键值对列表。它计算键的数量,初始化一个具有适当容量的 HashMap​,然后将每个键值对插入到 HashMap​中。
  4. HashMap 初始化

    • let _cap = hashmap!(@count key),*);​:使用 @count​内部宏规则来确定宏调用中提供的键的数量。
    • let mut _map = ::std::collections::HashMap::with_capacity(_cap);​:根据计算出的键的数量来初始化 HashMap​的容量。
    • key, $value);)*​:遍历所有键值对,并将它们插入到 HashMap​中。

使用示例

use std::collections::HashMap; fn main() { let mut map = hashmap!( "key1" => 1, "key2" => 2, "key3" => 3, ); assert_eq!(map.len(), 3); assert_eq!(map["key1"], 1); assert_eq!(map["key2"], 2); assert_eq!(map["key3"], 3); }

执行上述宏调用. 首先匹配 ,​结尾的几个部分

"key1" => 1, "key2" => 2, "key3" => 3,

对每个部分,再次调用 hashmap!($($key => $value),+)​ 这一次调用的就不再包含 ,​,所以会去执行另一个分支

fn main(){ // let _cap = hashmap!(@count $($key),*); // Note: 这里会调用内部辅助宏. let _cap = hashmap!(@count "key1", "key2", "key3"); // let mut _map = ::std::collections::HashMap::with_capacity(_cap); let mut _map= HashMap::with_capacity(_cap); //$( // let _ = _map.insert($key, $value); //)* // 重复执行三次上述片段 let _ = _map.insert("key1",1); let _ = _map.insert("key2",2); let _ = _map.insert("key3",3); return _map }

然后,对上述的执行结果,再次执行内部辅助宏 @count

(@count $($rest:expr),*) => (<[()]>::len(&[$(hashmap!(@single $rest)),*]));
  • (<[()]>::len(&[$(hashmap!(@single $rest)),*])​ 是宏展开的代码。这里使用了 Rust 的数组和类型推断机制来计算参数的数量。

    • <[()]>::len(&[...])​ 是一个类型推断的技巧,它创建了一个空元组 ()​ 的数组,并调用 .len()​ 方法来获取数组的长度。
    • $(hashmap!(@single $rest)),* ​ 是一个重复的宏调用,对于每个 $rest​ 表达式,它都会调用 hashmap!(@single ...) ​ 宏。

最后的生成结果如下:

fn main() { //let _cap = hashmap!(@count "key1", "key2", "key3"); let _cap = <[()]>::len(&[((),), ()]); // _cap = 3 }

<[()]>​是用于类型推断的语法,它指示编译器去推断数组的类型。这里的 <[()]>​并不是指一个数组字面量,而是一种特殊的语法结构,称为类型参数推断(type hint)。

具体来说,<[()]>​告诉编译器,我们想要一个数组,其元素类型为 ()​(空元组),并且希望编译器根据上下文推断出数组的具体类型。在这个例子中,.len()​方法需要一个数组引用作为参数,而 <[()]>​就是用来提供这个数组引用的类型信息

  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    58 引用 • 22 回帖 • 7 关注
  • Helix-editor
    1 引用

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
crowds21
不带评论的观察是人类智力的最高形式 北京

推荐标签 标签

  • 印象笔记
    3 引用 • 16 回帖
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    12 引用 • 54 回帖 • 8 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 76 关注
  • JSON

    JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。易于人类阅读和编写。同时也易于机器解析和生成。

    52 引用 • 190 回帖
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    35 引用 • 468 回帖 • 760 关注
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖 • 3 关注
  • Gzip

    gzip (GNU zip)是 GNU 自由软件的文件压缩程序。我们在 Linux 中经常会用到后缀为 .gz 的文件,它们就是 Gzip 格式的。现今已经成为互联网上使用非常普遍的一种数据压缩格式,或者说一种文件格式。

    9 引用 • 12 回帖 • 165 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    25241 引用 • 104137 回帖
  • sts
    2 引用 • 2 回帖 • 226 关注
  • HTML

    HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。

    108 引用 • 295 回帖 • 1 关注
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • Openfire

    Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。

    6 引用 • 7 回帖 • 105 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 1 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖 • 1 关注
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 159 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 4 关注
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 34 关注
  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    588 引用 • 3538 回帖
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 734 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    58 引用 • 25 回帖
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    181 引用 • 400 回帖 • 1 关注
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 642 关注
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 248 关注
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    124 引用 • 74 回帖
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖