rwa*_*ace 5 pattern-matching rust sum-type
我正在尝试解决 Rust 中的表达问题。我定义了一个总和类型的术语:
#[derive(Clone, Debug, PartialEq)]
pub enum Term {
True,
False,
Not(Box<Term>),
...
}
Run Code Online (Sandbox Code Playgroud)
编译器和文档说Box递归术语是必需的,因为结构不能包含自身(无限回归),并且仅仅简单地&Term不足以确定术语拥有其子术语。好的,到目前为止一切顺利。
现在我正在尝试编写一个函数,根据运算符的定义简化术语,例如 not true = false:
impl Term {
pub fn simplify(self) -> Term {
let a = self.map(Term::simplify);
match a {
Term::Not(Box(Term::True)) => Term::False,
_ => a,
}
}
pub fn map(self, f: fn(Term) -> Term) -> Term {
match self {
Term::True
| Term::False => self,
Term::Not(a) => Term::Not(Box::new(a.map(f))),
_ => panic!(),
}
}
}
Run Code Online (Sandbox Code Playgroud)
但编译器不喜欢我迄今为止尝试过的任何版本。
Term::Not(Term::True)无效,因为 aBox需要介于两者之间。
Term::Not(Box::new(Term::True))在创建术语时有效,但作为模式匹配表达式(不能包含函数调用)时无效。
Term::Not(Box(Term::True))也无效。
在 Rust 中执行此操作的正确方法是什么?
小智 5
编译器给出以下错误:
cannot match against a tuple struct which contains private fields。好的,让我们看看Box的定义(为了简单起见,我删除了特征边界):
pub struct Box<_>(Unique<T>, A);
Run Code Online (Sandbox Code Playgroud)
这看起来像错误消息中的元组。但它看起来内部值也不是公开的(这就是错误),所以你不能像这样构造盒子(Box(Term::True))。
我们可以做什么?您可以使用夜间功能box_patterns来创建盒子:
match a {
Term::Not(box Term::True) => Term::False,
_ => a,
}
Run Code Online (Sandbox Code Playgroud)
或者,我们尝试通过取消引用将值从盒子中提取出来(此处为boxed_value),然后检查内部值:
*boxed_value == Term::True
Run Code Online (Sandbox Code Playgroud)
您可以将其与以下内容结合if guards使用match:
match a {
Term::Not(content) if *content == Term::True => Term::False,
_ => a,
}
Run Code Online (Sandbox Code Playgroud)
我认为这种变体更好,特别是如果您还想从 映射Term::False到Term::True。
| 归档时间: |
|
| 查看次数: |
746 次 |
| 最近记录: |