Rust 创建递归枚举--我应该使用生存期引用吗?(锈迹)
我想创建一个ADT,如:Rust 创建递归枚举--我应该使用生存期引用吗?(锈迹),rust,reference,lifetime,algebraic-data-types,Rust,Reference,Lifetime,Algebraic Data Types,我想创建一个ADT,如: 发布枚举谓词,框), Bool(LogicOp、Literal、Literal) } 但显然,这不是指定寿命的正确方法 我的问题有两个方面: 在这里定义寿命的正确方法是什么 有没有更好的办法来解决这个问题? 我不想每次都克隆所有内容,因为所有内容都是不可变的,而且我不想创建多个副本。我还想做一些事情,比如 let foo=Predicate::Bool(无论参数是什么); let and=谓词::and(&foo,&foo); let neg=谓词::neg(&and
发布枚举谓词,框),
Bool(LogicOp、Literal、Literal)
}
但显然,这不是指定寿命的正确方法
我的问题有两个方面:
let foo=Predicate::Bool(无论参数是什么);
let and=谓词::and(&foo,&foo);
let neg=谓词::neg(&and);
设bar=谓词::And(&And,&neg);
以此类推,以后继续能够使用
foo
、和以及neg
。如果一切都是不变的,那么处理这种情况的最简单方法就是使用Rc
/Arc
(两者之间的唯一区别是后者可用于从多个线程访问的对象。)您可以按如下方式定义枚举:
pub enum Predicate {
And(Rc<Predicate>, Rc<Predicate>),
Neg(Rc<Predicate>),
Bool(LogicOp, Literal, Literal)
}
(从技术上讲,如果您不打算在以后使用,例如,neg
,则并非所有这些克隆都是必需的。)
简化此样板文件的一种方法是使用谓词
类型上的方法或相关函数来创建pre-Rc
ed值,如下所示:
impl Predicate {
pub fn and(a: &Rc<Predicate>, b: &Rc<Predicate>) -> Rc<Predicate> {
Rc::new(Predicate::And(a.clone(), b.clone())
}
pub fn neg(a: &Rc<Predicate>) -> Rc<Predicate> {
Rc::new(Predicate::Neg(a.clone()))
}
pub fn boolean(op: LogicOp, a: Literal, b: Literal) -> Rc<Predicate> {
Rc::new(Predicate::Bool(op, a, b))
}
}
但是,这种方法有一个不可避免的缺点。如果不首先取消引用,就无法通过Rc
匹配,这会使使用Rc
ADT有些痛苦。请参阅以了解详细信息。但显然这不是指定生命周期的正确方法。-您尝试过类似的方法吗:谢谢你!这看起来有点笨拙,来自Haskell…但我想当你对堆栈和堆有显式控制时,这是没有帮助的
impl Predicate {
pub fn and(a: &Rc<Predicate>, b: &Rc<Predicate>) -> Rc<Predicate> {
Rc::new(Predicate::And(a.clone(), b.clone())
}
pub fn neg(a: &Rc<Predicate>) -> Rc<Predicate> {
Rc::new(Predicate::Neg(a.clone()))
}
pub fn boolean(op: LogicOp, a: Literal, b: Literal) -> Rc<Predicate> {
Rc::new(Predicate::Bool(op, a, b))
}
}
let foo = Predicate::boolean(whatever args);
let and = Predicate::and(&foo, &foo);
let neg = Predicate::neg(&and);
let bar = Predicate::and(&and, &neg);