Recursion 在递归枚举上使用并行移动值错误

Recursion 在递归枚举上使用并行移动值错误,recursion,enums,rust,Recursion,Enums,Rust,我有一个递归的项结构,用于实现列表: #[derive(Debug)] pub enum Item<T> { Cons(T, Box<Item<T>>), Nil, } 建议分两步执行展开阶段,但此处不能使用,因为我们需要直接展开两个字段Cons(..)项,而不是嵌套项,如选项,其中可以应用两阶段技巧。我尝试的示例: pub fn add_after<T>(it: Box<Item<T>>, val: T)

我有一个递归的
结构,用于实现列表:

#[derive(Debug)]
pub enum Item<T> {
    Cons(T, Box<Item<T>>),
    Nil,
}
建议分两步执行展开阶段,但此处不能使用,因为我们需要直接展开两个字段
Cons(..)
项,而不是嵌套项,如
选项
,其中可以应用两阶段技巧。我尝试的示例:

pub fn add_after<T>(it: Box<Item<T>>, val: T) -> Box<Item<T>> {
    match *it {
        Item::Nil => return it,
        Item::Cons(..) => {
            let Item::Cons(a, b) = *it;
            let itm = Box::new(Item::Cons(val, b));
            return Box::new(Item::Cons(a, itm));
        }
    }
}
虽然我很确定这一点是详尽的,因为我们之前匹配了一个
Cons

你可能会患上这种疾病(另请参见哪个更接近复制),尽管今天的非词汇生存期并不能解决这个问题。这似乎排除了通过
对多个内容进行解构

这里有一种解决方法,尽管它不是最有效的方法,因为它会不必要地进行分配和重新分配:

#[derive(Debug)]
pub enum Item<T> {
    Cons(T, Box<Item<T>>),
    Nil,
}

pub fn add_after<T>(it: Box<Item<T>>, val: T) -> Box<Item<T>> {
    match { *it } {
        Item::Nil => Box::new(Item::Nil),
        Item::Cons(a, b) => {
            let itm = Box::new(Item::Cons(val, b));
            Box::new(Item::Cons(a, itm))
        }
    }
}

fn main() {}
另见:


Item::Nil大小写可能不匹配,因为此值对列表没有任何作用,因此可能不会传递给函数。但是,我们仍然必须创建两个新项目,而不是修改第一个项目,以避免一些alloc/free。
#[derive(Debug)]
pub enum Item<T> {
    Cons(T, Box<Item<T>>),
    Nil,
}

pub fn add_after<T>(it: Box<Item<T>>, val: T) -> Box<Item<T>> {
    match { *it } {
        Item::Nil => Box::new(Item::Nil),
        Item::Cons(a, b) => {
            let itm = Box::new(Item::Cons(val, b));
            Box::new(Item::Cons(a, itm))
        }
    }
}

fn main() {}
use std::mem;

pub fn add_after<T>(mut item: Box<Item<T>>, val: T) -> Box<Item<T>> {
    let unboxed_value = mem::replace(&mut *item, Item::Nil);

    match unboxed_value {
        Item::Nil => item,
        Item::Cons(a, b) => {
            let itm = Box::new(Item::Cons(val, b));
            *item = Item::Cons(a, itm);
            item
        }
    }
}