Helix-hashmap! 宏 解析

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

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 回帖 • 13 关注
  • Helix-editor
    1 引用

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 642 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    6 引用 • 143 回帖 • 1 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 66 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 349 关注
  • 博客

    记录并分享人生的经历。

    273 引用 • 2388 回帖 • 2 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 49 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 58 关注
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 518 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 248 回帖
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    954 引用 • 944 回帖 • 1 关注
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖 • 4 关注
  • jQuery

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

    63 引用 • 134 回帖 • 735 关注
  • Excel
    31 引用 • 28 回帖
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖
  • 反馈

    Communication channel for makers and users.

    120 引用 • 906 回帖 • 279 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    291 引用 • 4495 回帖 • 661 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    336 引用 • 324 回帖
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    115 引用 • 317 回帖
  • SVN

    SVN 是 Subversion 的简称,是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统,它的设计目标就是取代 CVS。

    29 引用 • 98 回帖 • 694 关注
  • Webswing

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

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

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    5 引用 • 16 回帖 • 1 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    43 引用 • 44 回帖 • 1 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    209 引用 • 2040 回帖
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 465 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 80 关注
  • Node.js

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

    139 引用 • 269 回帖