Rust Macros初学者指南✨ 揭开Rust最强大功能之一的神秘面纱。

Rust最强大和最强大的功能之一是它能够使用和创建宏。 不幸的是,创建宏的语法可能非常令人生畏,并且这些示例对于新手开发人员来说可能是压倒性的。

我保证Rust Macros真的很容易理解。 本文将为您提供如何创建自己的宏的先机。

什么是Rust的宏??

在这里插入图片描述

如果您已经尝试过Rust,那么您之前应该已经使用了一个宏,println!。 此宏允许您打印一行文本,并能够在文本字符串中插入变量。

宏只是允许您发明自己的语法并编写编写更多代码的代码。

这称为元编程,它允许使语法更短的语法糖,并使您更容易使用库。 您甚至可以在Rust中创建自己的DSL(特定于域的语言)。

宏通过匹配宏规则中定义的特定模式,将匹配的一部分捕获为变量,然后展开以生成更多代码。

如果你不理解其中一些,那也没关系。 让我们一起潜入!

我们如何创建宏??
我们可以使用macro_rules创建宏!宏。Macroception!

这就是你如何创建一个空白hey!宏 显然,现在它没有做任何事情。

在这里插入图片描述

那个()=> {}部分看起来很有趣,不是吗。

这是一个宏规则的条目,我们可以在一个宏中匹配许多规则。 它与模式匹配非常相似,我们也可以使用逗号分隔许多情况。

但是,它究竟意味着什么?

在这里插入图片描述

括号部分是匹配器,它允许我们匹配模式并捕获它们的一部分作为变量。 这就是我们如何发明自己的自定义语法和DSL。

花括号部分是抄写员,我们可以利用从匹配器中捕获的变量。 Rust编译器会将我们的宏代码及其变量扩展为实际的Rust代码。

匹配和捕捉模式✏️

我们如何实际匹配模式呢? 让我们来看看。

在这里插入图片描述

Rust将尝试匹配匹配器对中定义的模式,可以是(),{}或[]。 宏规则中的字符将与输入匹配,以确定它是否匹配。

在规则的模式成功匹配之后,我们可以捕获模式的一部分并将其捕获为变量以在转录器中使用。 这是你如何做到这一点。

美元符号后面的第一部分是变量的名称,它将在转录器中作为变量使用,这是我们的代码所在的位置。 在这个例子中,我们目前正在将其作为$ name捕获。

分号后面的最后一部分称为指示符,它们是我们可以选择匹配的类型。 例如,我们当前正在使用表达式指示符,如冒号后的expr所示。

这告诉Rust匹配表达式,并将其捕获为$ name。

我们可以使用许多指示符(https://danielkeep.github.io/practical-intro-to-macros.html),而不仅仅是表达式。 以下是Rust中可用指示符的快速列表:

  • item:例如函数,结构,模块等。
  • block:一个块(即一个语句块和/或一个表达式,用大括号括起来)
  • stmt:一份声明
  • pat: 一种模式
  • expr:一个表达式
  • ty:一种类型
  • ident:标识符
  • path:路径(例如foo,:: std :: mem :: replace,transmute :: <_,int>,…)
  • meta:元项目; 进入#[…]和#![…]属性的东西
  • tt:单个令牌树

现在,我们如何在转录器中使用这些捕获的变量?
在这里插入图片描述

很简单。 我们只使用我们在匹配器中捕获的捕获变量,这些变量以美元符号为前缀。 它就像一个普通变量一样工作; 这里没什么特别的

我们的第一个宏!?

酷! 我们现在知道足够的东西来创建一个简单的宏。 让我们创造我们自己的yo!宏。
在这里插入图片描述

就是这样,我们刚创建了第一个宏! 这个节目将打印出Yo,Finn! 作为调用宏的结果。

我们匹配了输入表达式并将其捕获为$ name变量。 然后,我们在转录器中使用捕获的$ name,它将由Rust编译器扩展。

那似乎很简单,不是吗?

重复,重复,重复,重复,重复,重复,重复,重复…

我们熟悉和喜爱的许多宏可以同时获取大量输入。 拿vec吧! 以宏为例; 我们可以通过调用vec创建一个带有项目的Vector! 像这样的宏:vec![1,2,3,4,5]。

vec怎么样! 去做? 它肯定不会捕获几千个变量并逐个手动推送它们,对吧? 这是秘密:

在这里插入图片描述

我们只是将我们想要重复的模式放在$(…)部分中。 然后,插入分隔符,在这种情况下是逗号(,)符号。 这将是将模式分开的角色,允许我们重复。

最后,我们在末尾添加星号(*)符号,它将重复匹配$()内的模式,直到匹配用完。

困惑? 我们来看一个例子吧!

在这里插入图片描述

在这种情况下,嘿! 宏,我们将所有输入表达式捕获为$ name,并且我们将继续匹配它,直到我们用完匹配。 我们可以使用尽可能多的参数来调用此宏。

仍然困惑? 那太好了! 让我们实现一个很棒的真实世界宏来看看它是如何工作的。

在Rust中实现Ruby的HashMap语法

如果您之前曾在Ruby中编程,那么您将知道其非常棒的哈希语法,key => value。 我很想拥有在Rust中创建HashMaps的语法!

幸运的是,我们可以使用宏,我们可以创建自己的语法,只需几行代码即可实现梦想。 (破坏者:七)

在这里插入图片描述

让我们开始吧。 我们可以使用$ key:expr => $ value:expr模式来捕获$ key和$ value表达式,用=>分隔。

这已经很好用了,但它只能让我们只匹配一个key => value对,这对于经常有多个键值对的HashMaps来说并不是很实用。 这就是明星(*)派上用场的地方。

在这里插入图片描述

通过将我们的模式放在$(),*中,我们允许重复该模式。 这意味着我们可以根据需要拥有尽可能多的key => value对。万岁!

在这里插入图片描述

调用宏时,将为每次重复分配捕获的变量。

但是,我们如何利用这些被重复的捕获变量呢? 当我们在抄录员中使用它们时,一切都变得清晰。

在这里插入图片描述

在转录员中,我们可以注意到在代码中使用$()*。 这意味着此代码将针对每个重复层进行专门扩展!

对于每个重复层,这将扩展为hm.insert()将$ key和$值放入HashMap。 让我们想象一下。

在这里插入图片描述

如你所见,当我们调用map!(“name”=>“Finn”,“gender”=>“Boy”)时,我们会产生两个重复层。

key => value对将转录为transcriber部分中指定的代码,它们被指定为hm.insert($ key,$ value),$ key和$ value是捕获的变量。

Phew,这是相当多的东西! 让我们把它们放在一起,创建我们自己的map!宏。

在这里插入图片描述

在七行代码中,我们创建了一个功能齐全的宏! 让我们创建一个程序并尝试调用它。 看看它是否有效。

在这里插入图片描述

该程序的输出是User {“gender”:“Boy”,“name”:“Finn”}。 在那里,它工作! 这就是我们如何在Rust中创建宏。

如果您想了解有关如何为Rust中的实际用法开发宏的更多信息,请查看以下资源:

就是这些!?

谢谢大家将它制作到最后! 我希望你终于有勇气创建自己的宏,并在Rust中实现你的元编程愿望。

在下一篇文章中见!✨

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值