我试图实现ConsList
个数据 struct ,它来自于函数范式语言,如Lisp或Haskell.下面是它的一些片段:
use ConsList::*;
enum ConsList<T> {
Empty,
List(T, Box<ConsList<T>>),
}
impl<T> ConsList<T> {
fn new() -> ConsList<T> {
Empty
}
// I don't know whether to use & or not at self parameter
fn insert_first(&mut self, value: T) -> &Self {
// unkown implementation
}
fn head(&mut self) -> Option<T> {
// unkown implementation
}
}
fn main() {
let mut list_var: ConsList<i32> = ConsList::new(); // Initiate
list_var.insert_first(2); // First insert
list_var.insert_first(1); // Second insert
}
我希望insert_first
函数的行为是这样的:
- 在新列表元组中的第一个位置创建
value
的新列表 - 将值移动到新列表的尾部
- 用新列表替换所有者变量(
list_var
)
例如,在启动时,list_var
变量的值为Empty
.然后,在第一次插入时,它将创建新值List(2, Empty)
,其中2
从value
移动,Empty
从Mutations 前的旧列表移动,我们将self
变量Mutations 为新列表.换句话说,我们Mutations 了list_var
个变量.关于更深入的内容,这里是我在第二次插入时所指的逐步:
- 将
list_var
(List(2, Empty)
)移至insert_first
方法中的参数self
- 将
1
移至insert_first
方法中的参数value
- 创建新列表,并将
value
和self
移至新列表List(3, List(2, Empty))
- 用新列表改变
self
,所以list_var
变量也将是新列表
这里的问题是,我们只能 Select :
- 在没有引用的情况下转移所有权(我们不能变异
list_var
) - 借入而不能移动(我们不能将旧列表移动到新列表)
据我所知,我们不能在转移所有权的同时又能够随着参照而变异.这是有用的,这是有原因的.方法head
将返回列表的第一个元素,并将列表变为尾部(我知道在函数式编程中不存在变异,但这将节省存储空间和复制新列表的性能).此方法需要能够对self
进行变异,将第一个元素移动到返回值,并将列表尾部的所有权移动到self
.
我试着用方框来表示间接性,但我仍然无法移动self.list
,因为它在引用后面
enum ConsListElem<T> {
Empty,
List(T, Box<ConsListElem<T>>),
}
pub struct ConstList<T> {
list: Box<ConsListElem<T>>,
}
impl<T> ConstList<T> {
pub fn cons(&mut self, value: T) -> &ConstList<T> {
self.list = Box::new(ConsListElem::List(value, self.list));
self
}
}