在 Rust 中,有没有一种方法可以对枚举成员进行“分组”,以便我可以获得谓词函数并在匹配语句中使用该谓词?
假设我有这个枚举:
enum Number {
One,
Two,
Three,
Four,
Five,
Six
}
这个谓词:
impl Number {
fn is_prime(&self) -> bool {
self == Number::Two || self == Number::Three || self == Number::Five
}
}
然后我的问题是,我的代码库周围有几个匹配语句,如果数字是素数,它们会以不同的方式处理事情:
match number {
Number::Two | Number::Three | Number::Five => {/* do something for primes*/}
Number::One => ...
Number::Four => ...
Number::Six => ...
}
我只想知道什么是素数的真相来源。当然,我可以在每个匹配语句之前添加谓词检查:
if number.is_prime() {
/* do something for primes*/
} else {
match number {
Number::One => ...
Number::Four => ...
Number::Six => ...
_ => {} // should never happen
}
}
但是后来我失去了详尽性检查。我需要添加一个包罗万象的手臂,它不能为我提供编译安全性,以确保后来将成员添加到
Number
的任何人都必须在每个 match
语句中显式处理它。
理想情况下我想做这样的事情:
match number {
is_prime() => {/* do something for primes*/}
Number::One => ...
Number::Four => ...
Number::Six => ...
}
有没有办法达到同样的目标?我想应该有一种方法可以通过宏来做到这一点,但我尽量避免使用宏,因为它们使代码不那么明确。
你可以制作一个宏:
#[macro_export]
macro_rules! primes {
() => {
$crate::Number::Two | $crate::Number::Three | $crate::Number::Five
};
}
impl Number {
pub fn factors(&self) -> u8 {
use Number::*;
match self {
primes!() => 2,
One => 1,
Four => 3,
Six => 4,
}
}
}
此宏假设
Number
在板条箱根中公开可用。如果在其他地方,请使用适当的路径。我认为没有办法避免为每个变体编写整个路径,因为模式中不能有 use
语句,尽管如果它非常长,您可以仅为路径部分创建另一个宏。 更多关于$crate
的信息请点击此处。
从好的方面来看,它确实可以作为更大模式的一部分:
primes!() | Number::One
如果您的组不同,您可以添加另一层枚举:
enum Numbers {
Prime(Prime),
NonPrime(NonPrime),
}
enum Prime {
Two,
Three,
Five,
}
enum NonPrime {
One,
Four,
Six,
}
然后就可以在外层搭配了:
use Number::*;
use Prime::*;
use NonPrime::*;
match number {
Prime(_) => todo!("do something for primes"),
NonPrime(One) => todo!("do something for one"),
NonPrime(_) => todo!("do something for other non primes"),
}