我正在用 Rust 编写一个类似Scheme 的语言的解释器。我将 AST 编码为枚举:
#[derive(Debug)]
pub enum Object {
Integer(i64),
Boolean(bool),
Character(char),
String(String),
Symbol(String),
Cons { car: Box<Object>, cdr: Box<Object> },
Nil,
}
pub type ObjectBox = Box<Object>;
Run Code Online (Sandbox Code Playgroud)
我想添加一个car(&self) -> ObjectBox方法到Object. 我想出了:
impl Object {
pub fn car(&self) -> Option<ObjectBox> {
match self {
Object::Cons { car, cdr: _ } => Some(ObjectBox::new(**car)),
_ => None,
}
}
}
Run Code Online (Sandbox Code Playgroud)
编译时我收到此错误:
error[E0507]: cannot move out of `**car` which is behind a shared reference
--> src/core/object.rs:94:65
|
94 | Object::Cons { car, cdr: _ } => Some(ObjectBox::new(**car)),
| ^^^^^ move occurs because `**car` has type `object::Object`, which does not implement the `Copy` trait
For more information about this error, try `rustc --explain E0507`.
Run Code Online (Sandbox Code Playgroud)
我明白为什么会发生错误,但我无法想出解决方法。Object我当前的实现可以做到这一点吗?
您无法移出 a &self,因此您几乎没有选择:
self:impl Object {
pub fn car(self) -> Option<ObjectBox> {
match self {
Object::Cons { car, cdr: _ } => Some(ObjectBox::new(*car)),
_ => None,
}
}
}
Run Code Online (Sandbox Code Playgroud)
pub type ObjectBox<'a> = Box<&'a Object>;
impl Object {
pub fn car(&self) -> Option<ObjectBox> {
match self {
Object::Cons { car, cdr: _ } => Some(ObjectBox::new(car.as_ref())),
_ => None,
}
}
}
Run Code Online (Sandbox Code Playgroud)
#[derive(Debug, Clone)]
pub enum Object {
Integer(i64),
Boolean(bool),
Character(char),
String(String),
Symbol(String),
Cons { car: Box<Object>, cdr: Box<Object> },
Nil,
}
pub type ObjectBox = Box<Object>;
impl Object {
pub fn car(&self) -> Option<ObjectBox> {
match self {
Object::Cons { car, cdr: _ } => Some(ObjectBox::new(*car.clone())),
_ => None,
}
}
}
Run Code Online (Sandbox Code Playgroud)
3.1 正如@KevinReid所建议的,您可以更改Box为Rc,这样您就可以获得指向该对象的廉价可克隆指针:
use std::rc::Rc;
#[derive(Debug, Clone)]
pub enum Object {
Integer(i64),
Boolean(bool),
Character(char),
String(String),
Symbol(String),
Cons { car: ObjectBox, cdr: ObjectBox },
Nil,
}
pub type ObjectBox = Rc<Object>;
impl Object {
pub fn car(&self) -> Option<ObjectBox> {
match self {
Object::Cons { car, cdr: _ } => Some(car.clone()),
_ => None,
}
}
}
Run Code Online (Sandbox Code Playgroud)