macros - 匹配封闭函数的返回类型

标签 macros rust return-type rust-macros

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 Errpanic!() 取决于返回类型。即:通过过程宏为您自己的宏执行宏调用步骤。

但是我认为这是一个坏主意,原因有几个。最重要的是,我不认为它在编译器调用过程宏时定义得很好。因此,编译器可能会在调用过程宏之前尝试调用您的 foo!() 宏。

所以它可以通过程序宏来工作,但不是以典型的方式。所以它相当hacky


我认为最好的解决方案

最后,我该怎么做? 让您的宏评估为 Result。然后用户可以轻松地自己决定如何处理它。如果他们返回一个 Result,他们只需要添加 ?。如果他们不这样做,他们可以自由选择 .unwrap()expect() 和其他 panic 方式。

我理解你为什么要尝试做你想做的事(这对用户来说更容易和舒适),但我认为这不是一个好主意。这可能归结为“远距离幽灵般的 Action ”:函数中宏的作用突然取决于该函数的返回类型。这意味着当你改变它时,函数的整个语义都会改变。这听起来很容易搬起石头砸自己的脚。这也可能是 Rust 不容易的原因。

关于macros - 匹配封闭函数的返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54346796/

相关文章:

Excel宏将数据行复制到底行

检查补丁宏错误

c++ - 我可以使用宏自动构建参数列表吗?

rust - 如何将特征与使用特征关联类型作为参数的超特征绑定(bind)?

Java接口(interface)和抽象中的返回类型

Rust 的 proc 宏的 C++ 替代品

rust - 为什么即使在本地安装后,rust 也无法为 openssl-sys v0.9.60 构建命令?

rust - Unwrap_or是否需要String或&str防 rust ?

java - 为什么java中的构造函数没有返回类型?

arrays - VBA 编译错误 : Can't Assign to Read-Only Property Returning Array from Custom Class Get Property