在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Rust最强大和最强大的功能之一是它能够使用和创建宏。 不幸的是,创建宏的语法可能非常令人生畏,并且这些示例对于新手开发人员来说可能是压倒性的。 我保证Rust Macros真的很容易理解。 本文将为您提供如何创建自己的宏的先机。 什么是Rust的宏??如果您已经尝试过Rust,那么您之前应该已经使用了一个宏,println!。 此宏允许您打印一行文本,并能够在文本字符串中插入变量。 宏只是允许您发明自己的语法并编写编写更多代码的代码。 这称为元编程,它允许使语法更短的语法糖,并使您更容易使用库。 您甚至可以在Rust中创建自己的DSL(特定于域的语言)。 宏通过匹配宏规则中定义的特定模式,将匹配的一部分捕获为变量,然后展开以生成更多代码。 如果你不理解其中一些,那也没关系。 让我们一起潜入! 我们如何创建宏?? 这就是你如何创建一个空白hey!宏 显然,现在它没有做任何事情。 那个()=> {}部分看起来很有趣,不是吗。 这是一个宏规则的条目,我们可以在一个宏中匹配许多规则。 它与模式匹配非常相似,我们也可以使用逗号分隔许多情况。 但是,它究竟意味着什么? 括号部分是匹配器,它允许我们匹配模式并捕获它们的一部分作为变量。 这就是我们如何发明自己的自定义语法和DSL。 花括号部分是抄写员,我们可以利用从匹配器中捕获的变量。 Rust编译器会将我们的宏代码及其变量扩展为实际的Rust代码。 匹配和捕捉模式✏️我们如何实际匹配模式呢? 让我们来看看。 Rust将尝试匹配匹配器对中定义的模式,可以是(),{}或[]。 宏规则中的字符将与输入匹配,以确定它是否匹配。 在规则的模式成功匹配之后,我们可以捕获模式的一部分并将其捕获为变量以在转录器中使用。 这是你如何做到这一点。 美元符号后面的第一部分是变量的名称,它将在转录器中作为变量使用,这是我们的代码所在的位置。 在这个例子中,我们目前正在将其作为$ name捕获。 分号后面的最后一部分称为指示符,它们是我们可以选择匹配的类型。 例如,我们当前正在使用表达式指示符,如冒号后的expr所示。 这告诉Rust匹配表达式,并将其捕获为$ name。 我们可以使用许多指示符(https://danielkeep.github.io/practical-intro-to-macros.html),而不仅仅是表达式。 以下是Rust中可用指示符的快速列表:
现在,我们如何在转录器中使用这些捕获的变量? 很简单。 我们只使用我们在匹配器中捕获的捕获变量,这些变量以美元符号为前缀。 它就像一个普通变量一样工作; 这里没什么特别的 我们的第一个宏!?酷! 我们现在知道足够的东西来创建一个简单的宏。 让我们创造我们自己的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中实现你的元编程愿望。 在下一篇文章中见!✨ |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论