将宏参数传递给其他宏

2024-03-21

我是生锈新手。我正在尝试创建宏,它需要一个缓冲区,然后从中解码一些数据并创建给定的变量列表。如果发生错误,那么它应该打印错误并继续,因为我将在接收缓冲区的循环中调用它。像这样的东西:-

for bin_ref in bufs {

   extract!( bin_ref anime &str episodes u32 season u32);

   //if everything goes ok then do some cool stuff with
   //above variables otherwise take next buf_ref    
}

我怎样才能做到这一点?所以我采用了这种方法:-

#[macro_export]
macro_rules! extract {

    ( $buf:ident $($var:ident $typ:ty),* ) => {
        $(
            ext_type!( $buf $var $typ );
        )*
    };
}

#[macro_export]
macro_rules! ext_type {
    ( $buf:ident $var:ident &str ) => {

        let mut $var : &str = ""; //some string specific function
        println!("doing cool things with '{}' which is string ",$var);        

    };
    ( $buf:ident $var:ident u32 ) => {
        let mut $var : u32 = 34; //some u32 specific function
        println!("doing cool things with '{}' which is u32",$var);
    }
}

我有以下测试功能:-

fn macro_test() {

    let mut bin_ref : &[u8] = &[0u8;100];

    ext_type!(bin_ref anime &str); // works
    ext_type!(bin_ref episodes u32 ); // works

    extract!( bin_ref username &str, password &str ); // does not work. why ??
}

当我编译这个时,我收到以下错误:-

error: no rules expected the token `&str`
  --> src/easycode.rs:11:34
   |
11 |             ext_type!( $buf $var $typ );
   |                                  ^^^^ no rules expected this token in macro call
...
19 | macro_rules! ext_type {
   | --------------------- when calling this macro
...
48 |     extract!( bin_ref username &str, password &str );
   |     ------------------------------------------------- in this macro invocation

为什么我不能直接通过$typ to ext_type!宏?从代码调用时它可以工作


The ext_type!宏的规则需要文字标记&str and u32在最后。这些文字标记cannot匹配匹配的片段$typ:ty in extract!。为了成功地将文字标记与匹配的片段匹配,它必须是一个tt, ident or lifetime https://doc.rust-lang.org/reference/macros-by-example.html#transcribing.

在这种情况下唯一有效的选择是tt https://doc.rust-lang.org/reference/macros.html#macro-invocation,简单地说,只是一个解析器标记。然而,一种类型通常由多个标记组成;例证&str,由两个标记组成& and str。因此,我们必须使用重复来完全捕获类型tts: $($typ:tt)+会做得很好。

使用无限重复tt然而,这是有代价的——tt将匹配几乎所有内容,因此只需替换$typ:ty with $($typ:tt)+不会工作,因为$typ重复将捕获所有内容,直到宏调用结束!为了防止这种情况发生,我们必须delimit https://doc.rust-lang.org/reference/tokens.html#delimiters宏规则匹配器中的类型标记树以阻止其消耗所有内容。以使调用稍微冗长为代价,将重复内容括在括号中将对我们很有帮助,并阻止令牌树完全匹配我们想要的位置。修改后的宏如下所示:

#[macro_export]
macro_rules! extract {
    ( $buf:ident $($var:ident ($($typ:tt)+)),* ) => {
        $(
            ext_type!( $buf $var $($typ)+);
        )*
    };
}

注意替换$typ:ty with ($($typ:tt)+)(这是一个用括号括起来的标记树重复)在匹配器中,并且替换$typ with $($typ)+在转录器中。

宏规则调用如下:

extract!(bin_ref username (&str), password (&str), id (u32));
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将宏参数传递给其他宏 的相关文章

随机推荐

  • 将值分配给特定的 data.table 列和行

    仍然理解这个伟大的包 有人可以解释一下这个错误的原因吗 谢谢 library data table DT lt data table id LETTERS var1 rnorm 26 var2 rnorm 26 gt DT 2 list v
  • 如何在heroku上的两个不同应用程序之间共享worker?

    我有两个独立的应用程序在heroku上运行并指向同一个数据库 第一个负责user interface第二个为admin interface 我在用sidekiq with redis对于后台作业处理 我添加了一个工作人员 并且可以通过设置指
  • 对大文件使用 Rijndael 加密

    我面临的情况是 我需要安全地加密 解密 n 长度的文件 最好使用 Rijndael 但绝对是 256 位加密 我以前玩过加密 并且非常高兴地加密 解密了字符串和字节数组 但是 因为我不知道文件的大小 并且有问题的文件可能非常大 2 5gb
  • 从 VB.NET 应用程序将文件发送到 PHP 脚本

    我需要将一些数据从内部网络上的 SQL DB 服务器发送到外部 Web 服务器 我希望通过编写一个每天调用一次的 VB NET 应用程序来实现此目的 该应用程序将大约 1 MB 的数据发送到 Web 服务器上的 PHP 脚本 然后将其存储在
  • node.js -- 同步执行命令并获取结果

    我试图在 node js 中同步执行 child process 是的 我知道这很糟糕 我有充分的理由 并检索 stdout 上的任何输出 但我不太清楚如何 我发现这个帖子 Node js同步执行系统命令 https stackoverfl
  • 如何在 VBA Sub 中应用 SumIf 公式?出现错误 1004

    我正在尝试创建一个 Sub 来放置SUMIF单元格中的公式 我已将问题简化为简单的设置 Private Sub CommandButton1 Click Cells 2 3 Formula SUMIF A1 A5 D1 B1 B5 End
  • Azure 云存储帐户的连接字符串

    如何创建到云存储帐户的连接字符串以便可以访问表 blob 和队列 示例代码表示赞赏 如果您在 Azure 门户中查看相关存储帐户下的内容 并查看左侧导航栏中的 访问密钥 项 则会显示提供的两个密钥以及访问存储帐户所需的整个连接字符串
  • 链接 C++ 流

    我正在考虑将几个 C iostream 链接 在一起以过滤输入两次 我正在使用 gzstreams 读取 zlib 压缩文件 并且正在考虑编码一个从流中读取并执行编码转换的流 也许通过传递一个打开的流作为构造函数参数 您认为这可以最好地实现
  • 水晶报表-关闭数据库连接

    这是C Visual Studio 2008 VS2008附带的水晶报表 我有一个驻留在 DLL 中的水晶报表查看器表单 DLL 负责加载水晶报表 基于报表文件名 并将报表显示在窗体上 当我完成水晶报表后 我对加载的报表文档对象调用 dis
  • Yeomen webapp 生成器在 Windows 上的 grunt 构建上失败

    我正在尝试 yeomen 脚手架工具 唯一的问题是我遇到了一些问题和咕噜声 我正在尝试使用 webapp 生成器组装一个简单的网站 搭建应用程序并使用grunt serve工作完美 仅在使用时失败grunt build 它失败并显示以下消息
  • 在for循环中取消NSOperation?

    我正在尝试使用在后台线程上实现搜索NSOperation on iOS 我不想子类化NSOperation所以这就是我正在做的 searchQueue cancelAllOperations NSInvocationOperation op
  • 成本函数和梯度似乎有效,但 scipy.optimize 函数无效

    我正在为 Andrew NG Coursera 课程编写 Matlab 代码 并将其转换为 python 我正在研究非正则化逻辑回归 在编写梯度和成本函数后 我需要类似于 fminunc 的东西 经过一番谷歌搜索后 我找到了几个选项 它们都
  • 防止 BoxLayout 扩展子项

    我想在 JPanel 内垂直堆叠一些 JComponent 以便它们堆叠在顶部 任何额外的空间都在底部 我正在使用 BoxLayout 每个组件都包含一个 JTextArea 必要时应允许文本换行 因此 基本上 我希望每个组件的高度是显示
  • 上传的日文和中文文件名编码问题

    我目前正在使用jQuery 文件上传 https github com blueimp jQuery File Upload 我可能会上传一些带有日文或中文文件名的文件 在浏览器的调试模式下我可以看到文件名例如是 疲 様 txt 或 测试文
  • 为什么链接器在未在任何地方指定的情况下寻找 python36_d.lib ?

    我正在编译Python C 扩展模块 https docs python org 3 6 extending building html使用 VS 2017 和 SWIG 扩展模块 pyd 文件 的链接器 用于调试配置 的命令是 OUT D
  • 将“\r\n”替换为“\n”

    我有一些文本数据打印出实际字符 r n 总共四个字符 我想用单个 n 字符替换这四个字符 但我似乎无法让 Python 为我做这件事 我目前正在尝试 mytext replace r n n 但这只是打印出 n 两个字符 而不是一个 我觉得
  • Objective-C 中的标记指针

    While 回答这个问题 https stackoverflow com a 20362087 115200我注意到现代 Objective C 运行时使用标记指针 这迈克 阿什 Mike Ash 的文章及其评论 http www mike
  • Linux下的Topshelf和.net core

    我有一个简单的应用程序 它使用 topshelf 作为服务启动 它看起来很简单 HostFactory Run x gt x Service
  • 在 Azure 逻辑应用中执行存储过程 - 错误网关错误

    当我从逻辑应用设计器执行存储过程时 出现严重的网关错误 我试图调用的存储过程 create procedure test as select from testable 测试表包含 100000 多行 存储过程的结果放置在Blob FTP中
  • 将宏参数传递给其他宏

    我是生锈新手 我正在尝试创建宏 它需要一个缓冲区 然后从中解码一些数据并创建给定的变量列表 如果发生错误 那么它应该打印错误并继续 因为我将在接收缓冲区的循环中调用它 像这样的东西 for bin ref in bufs extract b