Skip to content
On this page

智能指针1: exercises/smart_pointers/box1.rs

题目

rust
// box1.rs
//
// At compile time, Rust needs to know how much space a type takes up. This
// becomes problematic for recursive types, where a value can have as part of
// itself another value of the same type. To get around the issue, we can use a
// `Box` - a smart pointer used to store data on the heap, which also allows us
// to wrap a recursive type.
//
// The recursive type we're implementing in this exercise is the `cons list` - a
// data structure frequently found in functional programming languages. Each
// item in a cons list contains two elements: the value of the current item and
// the next item. The last item is a value called `Nil`.
//
// Step 1: use a `Box` in the enum definition to make the code compile
// Step 2: create both empty and non-empty cons lists by replacing `todo!()`
//
// Note: the tests should not be changed
//
// Execute `rustlings hint box1` or use the `hint` watch subcommand for a hint.

// I AM NOT DONE

#[derive(PartialEq, Debug)]
pub enum List {
    Cons(i32, List),
    Nil,
}

fn main() {
    println!("This is an empty cons list: {:?}", create_empty_list());
    println!(
        "This is a non-empty cons list: {:?}",
        create_non_empty_list()
    );
}

pub fn create_empty_list() -> List {
    todo!()
}

pub fn create_non_empty_list() -> List {
    todo!()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_create_empty_list() {
        assert_eq!(List::Nil, create_empty_list())
    }

    #[test]
    fn test_create_non_empty_list() {
        assert_ne!(create_empty_list(), create_non_empty_list())
    }
}

在编译时,Rust 需要知道每个类型占用了多少空间。 这对于递归类型来说是有问题的,因为一个值可以具有相同类型的另一个值作为其自身的一部分。 为了解决这个问题,我们可以使用Box——一个用于在堆上存储数据的智能指针,它还允许我们包装递归类型。

我们在本练习中实现的递归类型是 cons list - 函数式编程语言中常见的一种数据结构。 cons 列表中的每个项目都包含两个元素:当前项目的值和下一个项目的值。 最后一项是一个名为Nil的值。

  • 第1步:在枚举定义中使用 Box 来使代码编译
  • 第2步:通过替换 todo!() 创建空和非空 cons 列表

注意:不能修改单元测试代码。

题目解析

编译器提示的信息如下:

txt
⚠️  Compiling of exercises/smart_pointers/box1.rs failed! Please try again. Here's the output:
error[E0072]: recursive type `List` has infinite size
  --> exercises/smart_pointers/box1.rs:24:1
   |
24 | pub enum List {
   | ^^^^^^^^^^^^^
25 |     Cons(i32, List),
   |               ---- recursive without indirection
   |
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
   |
25 |     Cons(i32, Box<List>),
   |               ++++    +

error: aborting due to previous error

For more information about this error, try `rustc --explain E0072`.

编译器提示我们:

  • 递归类型List具有无限大小
  • 并提示我们可以添加智能指针,来打破循环,并且在代码上提示我们可以标注Box<List>

List大小不固定,意味着我们不知道该分配多少的空间来存储它,因此我们可以使用智能指针将其包裹起来。创建空的列表很简单,我们直接返回List::Nil就可以了,对于非空列表,我们只需要按照Cons的定义来创建即可。

rust
#[derive(PartialEq, Debug)]
pub enum List {
    Cons(i32, List), 
    Cons(i32, Box<List>), 
    Nil,
}

fn main() {
    println!("This is an empty cons list: {:?}", create_empty_list());
    println!(
        "This is a non-empty cons list: {:?}",
        create_non_empty_list()
    );
}

pub fn create_empty_list() -> List {
    todo!()
    List::Nil 
}

pub fn create_non_empty_list() -> List {
    todo!()
    List::Cons(10, Box::new(List::Nil)) 
}

参考资料

Powered by VitePress