我有如下代码:
enum Either<L, R> {
Left(L),
Right(R)
}
enum SomeMessageType {
// ...
}
fn do_something<T>() {
let data: Vec<Either<T, SomeMessageType>> = ...;
// ...
}
我希望能够在不显式指定Either
类型的情况下迭代data
的内容,因为必须在任何地方指定Either
会使API变得丑陋和讨厌。do_something
中的泛型类型T
将始终是一个枚举变量,我只是不知道是否可以用Rust的泛型类型来表示它。理想情况下,我希望能够写这样的东西:
fn do_something<...>() {
let data = ...;
matching_iterator!(data, {
SomeMessageType::... => ...
T::SomeVariant => ...
});
}
我已经试过编写这样的宏:
#[macro_export]
macro_rules! check_mail {
( $data:expr, { $( $pattern:pat => $handler:block )+ } ) => {
{
use $crate::build_pattern;
for data in $data.iter() {
if let $crate::build_pattern!($( $pattern )+) = message {
$( $handler )+
}
}
}
}
};
}
#[macro_export]
macro_rules! build_pattern {
( $pattern:pat ) => {
Either::Right($pattern)
};
( $pattern:pat ) => {
Either::Left($pattern)
};
}
但显然这段代码不会编译,更不用说运行了。我的直觉告诉我应该在每个模式的开头放一个区分器,这样更容易编写宏,但我一直无法让它工作。每次尝试都会生成错误的match arm代码,所有的匹配都在开头,然后所有的处理程序都在结尾,我不知道为什么。
2条答案
按热度按时间zbdgwd5y1#
你必须有一些方法来区分
Left
和Right
模式,我在这里使用了;
。此外,你不能匹配一个通用的变量,因为它可能是任何类型,甚至可能没有他们。
busg9geu2#
我可能是误解了,但你可能会隐藏一个或多个回调?
即:
然后,您可以使用这两种类型所需的任何处理程序来调用它:
这能解决您的问题吗?因为
Either
实现隐藏在do_something
中