3个版本
0.1.0 | 2023年9月16日 |
---|---|
0.1.0-alpha.1 | 2023年6月4日 |
#1927 in Rust模式
10KB
match-commutative ↔️
对模式进行交换律匹配,减少重复模式的使用。
文档
https://docs.rs/match-commutative
动机
当需要匹配三个形成交换律数学关系的值时,通常需要重复很多模式。让我们看看这可能会是什么样子
// imagine that these values come from somewhere and we need to match on them
let operant1 = Operant::Str(Some("42".into()));
let operant2 = Operant::Num(Some(1));
let operator = Operator::Plus;
match (operant1, operator, operant2) {
(
Operant::Str(Some(operant_str)),
Operator::Plus,
Operant::Num(Some(operant_num)),
)
| (
Operant::Num(Some(operant_num)),
Operator::Plus,
Operant::Str(Some(operant_str)),
) if operant_str.len() < 3 => {
let result = operant_num + operant_str.parse::<isize>().unwrap();
println!("Result is: {}", result);
}
(
Operant::Str(Some(operant_str)),
Operator::Mult,
Operant::Num(Some(operant_num)),
)
| (
Operant::Num(Some(operant_num)),
Operator::Mult,
Operant::Str(Some(operant_str)),
) if operant_str.len() < 3 => {
let result = operant_num * operant_str.parse::<isize>().unwrap();
println!("Result is: {}", result);
}
(_, _, _) => {
panic!("Not relevant for this example")
}
}
// Types that we use in this example
enum Operant {
Str(Option<String>),
Num(Option<isize>),
}
enum Operator {
Plus,
Mult,
Minus,
}
对于 Operator::{Plus, Mult}
,我们必须为每个模式都写两个完全相同的模式(用 |
(or-pattern) 连接它们)并执行相同的逻辑。模式中唯一的区别是操作数的顺序。不好!
使用 match-commutative
代替
使用 match-commutative
这可以简化为
use match_commutative::match_commutative;
// imagine that these values come from somewhere and we need to match on them
let operant1 = Operant::Str(Some("42".into()));
let operant2 = Operant::Num(Some(1));
let operator = Operator::Plus;
match_commutative!(
operant1,
operator,
operant2,
Operant::Str(Some(operant_str)),
Operator::Plus,
Operant::Num(Some(operant_num)) if operant_str.len() < 3 => {
let result = operant_num + operant_str.parse::<isize>().unwrap();
println!("Result is: {}", result);
},
Operant::Str(Some(operant_str)),
Operator::Mult,
Operant::Num(Some(operant_num)) if operant_str.len() < 3 => {
let result = operant_num * operant_str.parse::<isize>().unwrap();
println!("Result is: {}", result);
}
non_commut {
_, _, _ => {
// in `non_commut` block, patterns and their execution block behave exactly like std Rust
panic!("Not relevant for this example")
}
}
);
// Types that we use in this example
enum Operant {
Str(Option<String>),
Num(Option<isize>),
}
enum Operator {
Plus,
Mult,
Minus,
}
注意,在上面的示例中,operant1
和 operant2
的值可以互换,而仍然产生相同的程序输出。 因此,我们已经成功地在模式中避免了表达 顺序(在两个 Operant
之间不需要顺序)。✨
使用 non_commut
块匹配非交换律操作数
如果您需要匹配非交换律操作数,可以将模式放入可选的 non_commut
块中。在 non_commut
中模式的行为与 std Rust 完全相同
use match_commutative::match_commutative;
let operant1 = Operant::Str(Some("42".into()));
let operant2 = Operant::Num(Some(1));
let operator = Operator::Minus; // a non-commutative operator!
let result = match_commutative!(
operant2,
operator,
operant1,
Operant::Str(_),
Operator::Plus,
Operant::Num(_) => {
// do something here
todo!()
}
non_commut {
// for minus operations, we get different results depending on the
// ordering of the operants
Operant::Num(Some(op_num)),
Operator::Minus,
Operant::Str(Some(op_str)) if op_str.len() < 3 => {
op_num - op_str.parse::<isize>().unwrap()
},
Operant::Str(Some(op_str)),
Operator::Minus,
Operant::Num(Some(op_num)) if op_str.len() < 3 => {
op_str.parse::<isize>().unwrap() - op_num
},
_,_,_ => {
// catch all match arm
todo!()
}
}
);
assert_eq!(-41, result);
// Types that we use in this example
enum Operant {
Str(Option<String>),
Num(Option<isize>),
}
enum Operator {
Plus,
Mult,
Minus,
}
入门
在您的 Cargo.toml 文件中,在 [dependencies]
下添加以下行
match-commutative = "0.1.0"
安全性
该crate使用 100% 安全的Rust 实现,这通过使用 #![forbid(unsafe_code)]
来确保。
MSRV
此crate的最小支持的Rust版本为 1.54。MSRV的增加将通过小版本更改来指示(根据SemVer)。
许可证
许可协议为Apache License, Version 2.0或MIT许可协议,您可任选其一。除非您明确声明,否则您有意提交以包含在本crate中的任何贡献,如Apache-2.0许可协议中定义,将按上述方式双重许可,不附加任何额外条款或条件。