Helix-hashmap! 宏 解析

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

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

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    71 引用 • 535 回帖 • 834 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    411 引用 • 3588 回帖
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖 • 2 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    693 引用 • 537 回帖
  • Gzip

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

    9 引用 • 12 回帖 • 170 关注
  • 程序员

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

    588 引用 • 3528 回帖
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 610 关注
  • Access
    1 引用 • 3 回帖 • 4 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3455 回帖 • 151 关注
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    9 引用 • 15 回帖 • 6 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖 • 2 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    7 引用 • 69 回帖 • 6 关注
  • Notion

    Notion - The all-in-one workspace for your notes, tasks, wikis, and databases.

    10 引用 • 77 回帖
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    56 引用 • 85 回帖
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    167 引用 • 408 回帖 • 489 关注
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖
  • CSDN

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

    14 引用 • 155 回帖
  • 叶归
    9 引用 • 43 回帖 • 22 关注
  • Android

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

    336 引用 • 324 回帖 • 1 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    12 引用 • 5 回帖 • 634 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    76 引用 • 258 回帖 • 626 关注
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    23 引用 • 32 回帖
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 273 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 92 关注
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 558 关注
  • gRpc
    11 引用 • 9 回帖 • 96 关注