- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Rust 宏是否可以匹配封闭函数的返回类型?
一个例子类似于日志记录和断言宏,它在返回 Result
的函数中返回 Err
,在不返回 Result
的函数中返回 panic。要实现这一点,宏应该以某种方式知道封闭函数的返回类型。
我想这对于声明性宏 (macro_rules!
) 是不可能的,因为它们只有一组有限的匹配类型(如 The Rust Reference, chapter Macros By Example 中所述):项、 block 、语句、模式、表达式、类型、标识符等,但不是封闭函数的返回类型。
但也许使用过程宏?
最佳答案
总结:不,即使使用程序宏也不容易做到。我实际上认为你不应该写这样的东西,即使它是可能的。只需让您的宏评估为 Result
并让用户处理它。
Rust 宏,过程的和声明的,只能访问它们的输入流:只是一个标记列表。对于类似函数的宏(您通过 foo!(...)
调用的宏),输入就是您传递给它们的内容。所以您可以手动传递返回类型:
macro_rules! foo {
(Result $($stuff:tt)*) => { return Err(()); };
($($stuff:tt)*) => { panic!(); };
}
fn returns_result() -> Result<String, ()> {
foo!(Result<(), ()>); // will return `Err`
Ok("hi".into())
}
fn returns_string() -> String {
foo!(String); // will panic
"hi".into()
}
但我想这不是您想要的:用户必须手动指定每个宏调用的返回类型。
以这种方式调用的过程宏也是如此。
我们可以定义一个过程宏,其中函数的返回类型在输入标记流中吗?是的,最好通过 proc-macro 属性。如果你定义这样一个属性 bar
,你可以这样写:
#[bar]
fn returns_result() -> Result<String, ()> { ... }
并且您的过程宏将接收整个函数定义作为输入,包括返回类型。 但是您将如何处理这些信息?
您可以根据需要更改整个函数,因此一种想法是搜索函数中所有 foo!()
宏调用并将它们替换为 return Err
或 panic!()
取决于返回类型。即:通过过程宏为您自己的宏执行宏调用步骤。
但是我认为这是一个坏主意,原因有几个。最重要的是,我不认为它在编译器调用过程宏时定义得很好。因此,编译器可能会在调用过程宏之前尝试调用您的 foo!()
宏。
所以它可以通过程序宏来工作,但不是以典型的方式。所以它相当hacky。
最后,我该怎么做? 让您的宏评估为 Result
。然后用户可以轻松地自己决定如何处理它。如果他们返回一个 Result
,他们只需要添加 ?
。如果他们不这样做,他们可以自由选择 .unwrap()
、expect()
和其他 panic 方式。
我理解你为什么要尝试做你想做的事(这对用户来说更容易和舒适),但我认为这不是一个好主意。这可能归结为“远距离幽灵般的 Action ”:函数中宏的作用突然取决于该函数的返回类型。这意味着当你改变它时,函数的整个语义都会改变。这听起来很容易搬起石头砸自己的脚。这也可能是 Rust 不容易的原因。
关于macros - 匹配封闭函数的返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54346796/
从the documentation, 13.5.5: When the last parameter of a method is a closure, you can place the clos
Bjarne Stroustrup 写道: “友元类必须事先在封闭范围内声明或在非类范围内定义,立即封闭声明它为友元的类” 语句的第一部分不是多余的,因为“立即包含类的非类范围”包括“先前在封闭范围中
我有一个网格(如下例),其中包含外墙(标记为 W)、环境 block (E)、开放空间 (o) 和事件点 (A)。目前,此网格存储在 [,] 中,其中包含与给定点关联的所有数据。我试图确定是否包含一个
我正在尝试使用 this blogpost's approach to higher-kinded data without dangling Identity functors for the tr
在下面的代码中: package main import ( "fmt" "time" ) func asChan(vs ...int) <-chan int { c := m
我在传递和评估闭包列表时遇到困难。经过大量简化,该程序显示出与我正在尝试编写的程序相同的错误: use std::vec::flat_map; #[main] fn main() { let li
我正在努力成为一名好公民,并尽可能远离全局范围。有没有办法访问不在全局范围内的 setTimeout 变量? 因此,在此示例中,某人将如何取消“计时器”? myObject.timedAction =
考虑这个例子: def A(): b = 1 def B(): # I can access 'b' from here. print(b)
val listPlans: List = newPlans.mapTry { it.data.map { Plan(it.id, it.nam
我目前正在尝试使用SinonJS对我的 angular.service 进行单元测试,但是遇到了一个问题,希望有人可以阐明为什么会发生这种情况。我已经重构了当前的项目以说明当前的问题。 我还提供了DE
我正在使用 Go channel ,我想知道关闭 channel 和将其设置为 nil 之间有什么区别? 编辑: 在此example ,我想通过关闭 channel 或设置为零来断开发送者和接收者的连
我的应用程序有一个奇怪的行为,我不知道它来自哪里。我已经为 TextView 内容实现了 NSScanner,效果非常好。扫描器与文本存储结合使用,通过 TextView 委托(delegate)方法
我不知道如何让 MyBatis 生成封闭的 or 语句: WHERE x.token = ? AND ( (x.scene = 'A' OR x.scene = 'B')) 这是一个令人惊讶的简单
我不希望这是一个摄像头检测程序。这是一个程序,可以检测应用程序屏幕上颜色的传递。 我想要做的是检测大于 5x5 像素的黑色何时穿过屏幕上定义的空间区域。我想过用一个大区域来拉伸(stretch)整个宽
我一直在使用 RDFLib 来解析数据并将其插入到三元组中。我遇到的一个常见问题是,从关联数据存储库解析时,没有尖括号括起 URL。 要上传数据,我必须手动添加 并使用 URIRef重新创建 URL。
我已经阅读了很多有关此问题的帖子,但我仍然不确定我是否完全理解这些定义。 以下是我认为不同术语的示例。我是否走在正确的轨道上,或者我仍然不理解这些概念。谢谢 Array - unbound and o
我为我的 Android 应用设置了 GooglePlay 内部和封闭式 Alpha 测试设置。 它非常适合允许测试人员加入计划并安装应用程序,但是当我从测试人员电子邮件列表中删除测试人员时,他们仍然
我是一名优秀的程序员,十分优秀!